@react-x11/components 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +979 -21
- package/dist/ansi/cast.d.ts +48 -0
- package/dist/ansi/cast.d.ts.map +1 -0
- package/dist/ansi/cast.js +135 -0
- package/dist/ansi/cast.js.map +1 -0
- package/dist/ansi/index.d.ts +10 -0
- package/dist/ansi/index.d.ts.map +1 -0
- package/dist/ansi/index.js +27 -0
- package/dist/ansi/index.js.map +1 -0
- package/dist/ansi/palette.d.ts +79 -0
- package/dist/ansi/palette.d.ts.map +1 -0
- package/dist/ansi/palette.js +155 -0
- package/dist/ansi/palette.js.map +1 -0
- package/dist/ansi/parse.d.ts +114 -0
- package/dist/ansi/parse.d.ts.map +1 -0
- package/dist/ansi/parse.js +687 -0
- package/dist/ansi/parse.js.map +1 -0
- package/dist/ansi/sgr.d.ts +87 -0
- package/dist/ansi/sgr.d.ts.map +1 -0
- package/dist/ansi/sgr.js +302 -0
- package/dist/ansi/sgr.js.map +1 -0
- package/dist/ansi/utf8.d.ts +15 -0
- package/dist/ansi/utf8.d.ts.map +1 -0
- package/dist/ansi/utf8.js +82 -0
- package/dist/ansi/utf8.js.map +1 -0
- package/dist/calendar/Calendar.d.ts +136 -0
- package/dist/calendar/Calendar.d.ts.map +1 -0
- package/dist/calendar/Calendar.js +460 -0
- package/dist/calendar/Calendar.js.map +1 -0
- package/dist/calendar/DatePicker.d.ts +52 -0
- package/dist/calendar/DatePicker.d.ts.map +1 -0
- package/dist/calendar/DatePicker.js +257 -0
- package/dist/calendar/DatePicker.js.map +1 -0
- package/dist/calendar/dates.d.ts +90 -0
- package/dist/calendar/dates.d.ts.map +1 -0
- package/dist/calendar/dates.js +236 -0
- package/dist/calendar/dates.js.map +1 -0
- package/dist/calendar/index.d.ts +8 -0
- package/dist/calendar/index.d.ts.map +1 -0
- package/dist/calendar/index.js +15 -0
- package/dist/calendar/index.js.map +1 -0
- package/dist/charts/components.d.ts +141 -0
- package/dist/charts/components.d.ts.map +1 -0
- package/dist/charts/components.js +580 -0
- package/dist/charts/components.js.map +1 -0
- package/dist/charts/data.d.ts +198 -0
- package/dist/charts/data.d.ts.map +1 -0
- package/dist/charts/data.js +616 -0
- package/dist/charts/data.js.map +1 -0
- package/dist/charts/hx.d.ts +21 -0
- package/dist/charts/hx.d.ts.map +1 -0
- package/dist/charts/hx.js +15 -0
- package/dist/charts/hx.js.map +1 -0
- package/dist/charts/index.d.ts +27 -0
- package/dist/charts/index.d.ts.map +1 -0
- package/dist/charts/index.js +38 -0
- package/dist/charts/index.js.map +1 -0
- package/dist/charts/node.d.ts +96 -0
- package/dist/charts/node.d.ts.map +1 -0
- package/dist/charts/node.js +720 -0
- package/dist/charts/node.js.map +1 -0
- package/dist/charts/render.d.ts +153 -0
- package/dist/charts/render.d.ts.map +1 -0
- package/dist/charts/render.js +762 -0
- package/dist/charts/render.js.map +1 -0
- package/dist/charts/scale.d.ts +42 -0
- package/dist/charts/scale.d.ts.map +1 -0
- package/dist/charts/scale.js +173 -0
- package/dist/charts/scale.js.map +1 -0
- package/dist/charts/spec.d.ts +91 -0
- package/dist/charts/spec.d.ts.map +1 -0
- package/dist/charts/spec.js +33 -0
- package/dist/charts/spec.js.map +1 -0
- package/dist/charts/timers.d.ts +6 -0
- package/dist/charts/timers.d.ts.map +1 -0
- package/dist/charts/timers.js +14 -0
- package/dist/charts/timers.js.map +1 -0
- package/dist/code/hx.d.ts +24 -0
- package/dist/code/hx.d.ts.map +1 -0
- package/dist/code/hx.js +25 -0
- package/dist/code/hx.js.map +1 -0
- package/dist/code/index.d.ts +45 -0
- package/dist/code/index.d.ts.map +1 -0
- package/dist/code/index.js +93 -0
- package/dist/code/index.js.map +1 -0
- package/dist/code-editor/completion.d.ts +26 -0
- package/dist/code-editor/completion.d.ts.map +1 -0
- package/dist/code-editor/completion.js +129 -0
- package/dist/code-editor/completion.js.map +1 -0
- package/dist/code-editor/doc.d.ts +35 -0
- package/dist/code-editor/doc.d.ts.map +1 -0
- package/dist/code-editor/doc.js +162 -0
- package/dist/code-editor/doc.js.map +1 -0
- package/dist/code-editor/hx.d.ts +13 -0
- package/dist/code-editor/hx.d.ts.map +1 -0
- package/dist/code-editor/hx.js +10 -0
- package/dist/code-editor/hx.js.map +1 -0
- package/dist/code-editor/index.d.ts +88 -0
- package/dist/code-editor/index.d.ts.map +1 -0
- package/dist/code-editor/index.js +401 -0
- package/dist/code-editor/index.js.map +1 -0
- package/dist/code-editor/node.d.ts +343 -0
- package/dist/code-editor/node.d.ts.map +1 -0
- package/dist/code-editor/node.js +1521 -0
- package/dist/code-editor/node.js.map +1 -0
- package/dist/code-language/hljs.d.ts +47 -0
- package/dist/code-language/hljs.d.ts.map +1 -0
- package/dist/code-language/hljs.js +211 -0
- package/dist/code-language/hljs.js.map +1 -0
- package/dist/code-language/index.d.ts +22 -0
- package/dist/code-language/index.d.ts.map +1 -0
- package/dist/code-language/index.js +20 -0
- package/dist/code-language/index.js.map +1 -0
- package/dist/code-language/languages/glsl.d.ts +4 -0
- package/dist/code-language/languages/glsl.d.ts.map +1 -0
- package/dist/code-language/languages/glsl.js +99 -0
- package/dist/code-language/languages/glsl.js.map +1 -0
- package/dist/code-language/languages/javascript.d.ts +10 -0
- package/dist/code-language/languages/javascript.d.ts.map +1 -0
- package/dist/code-language/languages/javascript.js +360 -0
- package/dist/code-language/languages/javascript.js.map +1 -0
- package/dist/code-language/languages/json.d.ts +4 -0
- package/dist/code-language/languages/json.d.ts.map +1 -0
- package/dist/code-language/languages/json.js +68 -0
- package/dist/code-language/languages/json.js.map +1 -0
- package/dist/code-language/languages/shell.d.ts +4 -0
- package/dist/code-language/languages/shell.d.ts.map +1 -0
- package/dist/code-language/languages/shell.js +189 -0
- package/dist/code-language/languages/shell.js.map +1 -0
- package/dist/code-language/languages/sql.d.ts +11 -0
- package/dist/code-language/languages/sql.d.ts.map +1 -0
- package/dist/code-language/languages/sql.js +133 -0
- package/dist/code-language/languages/sql.js.map +1 -0
- package/dist/code-language/lezer.d.ts +24 -0
- package/dist/code-language/lezer.d.ts.map +1 -0
- package/dist/code-language/lezer.js +148 -0
- package/dist/code-language/lezer.js.map +1 -0
- package/dist/code-language/registry.d.ts +19 -0
- package/dist/code-language/registry.d.ts.map +1 -0
- package/dist/code-language/registry.js +56 -0
- package/dist/code-language/registry.js.map +1 -0
- package/dist/code-language/runs.d.ts +35 -0
- package/dist/code-language/runs.d.ts.map +1 -0
- package/dist/code-language/runs.js +88 -0
- package/dist/code-language/runs.js.map +1 -0
- package/dist/code-language/stream.d.ts +70 -0
- package/dist/code-language/stream.d.ts.map +1 -0
- package/dist/code-language/stream.js +243 -0
- package/dist/code-language/stream.js.map +1 -0
- package/dist/code-language/textmate.d.ts +27 -0
- package/dist/code-language/textmate.d.ts.map +1 -0
- package/dist/code-language/textmate.js +86 -0
- package/dist/code-language/textmate.js.map +1 -0
- package/dist/code-language/theme.d.ts +26 -0
- package/dist/code-language/theme.d.ts.map +1 -0
- package/dist/code-language/theme.js +108 -0
- package/dist/code-language/theme.js.map +1 -0
- package/dist/code-language/timers.d.ts +7 -0
- package/dist/code-language/timers.d.ts.map +1 -0
- package/dist/code-language/timers.js +22 -0
- package/dist/code-language/timers.js.map +1 -0
- package/dist/code-language/types.d.ts +173 -0
- package/dist/code-language/types.d.ts.map +1 -0
- package/dist/code-language/types.js +41 -0
- package/dist/code-language/types.js.map +1 -0
- package/dist/codeblock/index.d.ts +69 -0
- package/dist/codeblock/index.d.ts.map +1 -0
- package/dist/codeblock/index.js +85 -0
- package/dist/codeblock/index.js.map +1 -0
- package/dist/color-picker/ColorField.d.ts +39 -0
- package/dist/color-picker/ColorField.d.ts.map +1 -0
- package/dist/color-picker/ColorField.js +239 -0
- package/dist/color-picker/ColorField.js.map +1 -0
- package/dist/color-picker/ColorPicker.d.ts +109 -0
- package/dist/color-picker/ColorPicker.d.ts.map +1 -0
- package/dist/color-picker/ColorPicker.js +757 -0
- package/dist/color-picker/ColorPicker.js.map +1 -0
- package/dist/color-picker/color.d.ts +105 -0
- package/dist/color-picker/color.d.ts.map +1 -0
- package/dist/color-picker/color.js +313 -0
- package/dist/color-picker/color.js.map +1 -0
- package/dist/color-picker/index.d.ts +8 -0
- package/dist/color-picker/index.d.ts.map +1 -0
- package/dist/color-picker/index.js +19 -0
- package/dist/color-picker/index.js.map +1 -0
- package/dist/desktop-calendar/eds.d.ts +102 -0
- package/dist/desktop-calendar/eds.d.ts.map +1 -0
- package/dist/desktop-calendar/eds.js +356 -0
- package/dist/desktop-calendar/eds.js.map +1 -0
- package/dist/desktop-calendar/ical.d.ts +63 -0
- package/dist/desktop-calendar/ical.d.ts.map +1 -0
- package/dist/desktop-calendar/ical.js +57 -0
- package/dist/desktop-calendar/ical.js.map +1 -0
- package/dist/desktop-calendar/index.d.ts +72 -0
- package/dist/desktop-calendar/index.d.ts.map +1 -0
- package/dist/desktop-calendar/index.js +213 -0
- package/dist/desktop-calendar/index.js.map +1 -0
- package/dist/embed/client.d.ts +121 -0
- package/dist/embed/client.d.ts.map +1 -0
- package/dist/embed/client.js +203 -0
- package/dist/embed/client.js.map +1 -0
- package/dist/embed/host.d.ts +96 -0
- package/dist/embed/host.d.ts.map +1 -0
- package/dist/embed/host.js +266 -0
- package/dist/embed/host.js.map +1 -0
- package/dist/embed/index.d.ts +5 -0
- package/dist/embed/index.d.ts.map +1 -0
- package/dist/embed/index.js +13 -0
- package/dist/embed/index.js.map +1 -0
- package/dist/embed/timers.d.ts +6 -0
- package/dist/embed/timers.d.ts.map +1 -0
- package/dist/embed/timers.js +16 -0
- package/dist/embed/timers.js.map +1 -0
- package/dist/flow/draw.d.ts +45 -0
- package/dist/flow/draw.d.ts.map +1 -0
- package/dist/flow/draw.js +295 -0
- package/dist/flow/draw.js.map +1 -0
- package/dist/flow/index.d.ts +64 -0
- package/dist/flow/index.d.ts.map +1 -0
- package/dist/flow/index.js +306 -0
- package/dist/flow/index.js.map +1 -0
- package/dist/flow/model.d.ts +158 -0
- package/dist/flow/model.d.ts.map +1 -0
- package/dist/flow/model.js +566 -0
- package/dist/flow/model.js.map +1 -0
- package/dist/flow/node.d.ts +429 -0
- package/dist/flow/node.d.ts.map +1 -0
- package/dist/flow/node.js +3025 -0
- package/dist/flow/node.js.map +1 -0
- package/dist/flow/paths.d.ts +43 -0
- package/dist/flow/paths.d.ts.map +1 -0
- package/dist/flow/paths.js +327 -0
- package/dist/flow/paths.js.map +1 -0
- package/dist/flow/types.d.ts +561 -0
- package/dist/flow/types.d.ts.map +1 -0
- package/dist/flow/types.js +2 -0
- package/dist/flow/types.js.map +1 -0
- package/dist/formula/hx.d.ts +24 -0
- package/dist/formula/hx.d.ts.map +1 -0
- package/dist/formula/hx.js +25 -0
- package/dist/formula/hx.js.map +1 -0
- package/dist/formula/index.d.ts +74 -0
- package/dist/formula/index.d.ts.map +1 -0
- package/dist/formula/index.js +155 -0
- package/dist/formula/index.js.map +1 -0
- package/dist/formula/katex.d.ts +78 -0
- package/dist/formula/katex.d.ts.map +1 -0
- package/dist/formula/katex.js +130 -0
- package/dist/formula/katex.js.map +1 -0
- package/dist/formula/layout.d.ts +103 -0
- package/dist/formula/layout.d.ts.map +1 -0
- package/dist/formula/layout.js +716 -0
- package/dist/formula/layout.js.map +1 -0
- package/dist/formula/node.d.ts +50 -0
- package/dist/formula/node.d.ts.map +1 -0
- package/dist/formula/node.js +351 -0
- package/dist/formula/node.js.map +1 -0
- package/dist/html/controls.d.ts +48 -0
- package/dist/html/controls.d.ts.map +1 -0
- package/dist/html/controls.js +195 -0
- package/dist/html/controls.js.map +1 -0
- package/dist/html/css/cascade.d.ts +51 -0
- package/dist/html/css/cascade.d.ts.map +1 -0
- package/dist/html/css/cascade.js +552 -0
- package/dist/html/css/cascade.js.map +1 -0
- package/dist/html/css/parse.d.ts +74 -0
- package/dist/html/css/parse.d.ts.map +1 -0
- package/dist/html/css/parse.js +464 -0
- package/dist/html/css/parse.js.map +1 -0
- package/dist/html/css/style.d.ts +142 -0
- package/dist/html/css/style.d.ts.map +1 -0
- package/dist/html/css/style.js +1145 -0
- package/dist/html/css/style.js.map +1 -0
- package/dist/html/css/ua.d.ts +5 -0
- package/dist/html/css/ua.d.ts.map +1 -0
- package/dist/html/css/ua.js +171 -0
- package/dist/html/css/ua.js.map +1 -0
- package/dist/html/css/values.d.ts +78 -0
- package/dist/html/css/values.d.ts.map +1 -0
- package/dist/html/css/values.js +330 -0
- package/dist/html/css/values.js.map +1 -0
- package/dist/html/dom.d.ts +112 -0
- package/dist/html/dom.d.ts.map +1 -0
- package/dist/html/dom.js +374 -0
- package/dist/html/dom.js.map +1 -0
- package/dist/html/hx.d.ts +24 -0
- package/dist/html/hx.d.ts.map +1 -0
- package/dist/html/hx.js +29 -0
- package/dist/html/hx.js.map +1 -0
- package/dist/html/index.d.ts +137 -0
- package/dist/html/index.d.ts.map +1 -0
- package/dist/html/index.js +339 -0
- package/dist/html/index.js.map +1 -0
- package/dist/html/layout/block.d.ts +58 -0
- package/dist/html/layout/block.d.ts.map +1 -0
- package/dist/html/layout/block.js +724 -0
- package/dist/html/layout/block.js.map +1 -0
- package/dist/html/layout/boxes.d.ts +261 -0
- package/dist/html/layout/boxes.d.ts.map +1 -0
- package/dist/html/layout/boxes.js +725 -0
- package/dist/html/layout/boxes.js.map +1 -0
- package/dist/html/layout/flex.d.ts +16 -0
- package/dist/html/layout/flex.d.ts.map +1 -0
- package/dist/html/layout/flex.js +242 -0
- package/dist/html/layout/flex.js.map +1 -0
- package/dist/html/layout/floats.d.ts +50 -0
- package/dist/html/layout/floats.d.ts.map +1 -0
- package/dist/html/layout/floats.js +110 -0
- package/dist/html/layout/floats.js.map +1 -0
- package/dist/html/layout/inline.d.ts +44 -0
- package/dist/html/layout/inline.d.ts.map +1 -0
- package/dist/html/layout/inline.js +700 -0
- package/dist/html/layout/inline.js.map +1 -0
- package/dist/html/layout/table.d.ts +5 -0
- package/dist/html/layout/table.d.ts.map +1 -0
- package/dist/html/layout/table.js +340 -0
- package/dist/html/layout/table.js.map +1 -0
- package/dist/html/node.d.ts +149 -0
- package/dist/html/node.d.ts.map +1 -0
- package/dist/html/node.js +861 -0
- package/dist/html/node.js.map +1 -0
- package/dist/html/paint.d.ts +48 -0
- package/dist/html/paint.d.ts.map +1 -0
- package/dist/html/paint.js +495 -0
- package/dist/html/paint.js.map +1 -0
- package/dist/html/resources.d.ts +48 -0
- package/dist/html/resources.d.ts.map +1 -0
- package/dist/html/resources.js +156 -0
- package/dist/html/resources.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/heights.d.ts +81 -0
- package/dist/internal/heights.d.ts.map +1 -0
- package/dist/internal/heights.js +193 -0
- package/dist/internal/heights.js.map +1 -0
- package/dist/internal/hx.d.ts +24 -0
- package/dist/internal/hx.d.ts.map +1 -0
- package/dist/internal/hx.js +27 -0
- package/dist/internal/hx.js.map +1 -0
- package/dist/internal/text.d.ts +6 -0
- package/dist/internal/text.d.ts.map +1 -0
- package/dist/internal/text.js +44 -0
- package/dist/internal/text.js.map +1 -0
- package/dist/internal/timers.d.ts +8 -0
- package/dist/internal/timers.d.ts.map +1 -0
- package/dist/internal/timers.js +22 -0
- package/dist/internal/timers.js.map +1 -0
- package/dist/internal/widget.d.ts +40 -0
- package/dist/internal/widget.d.ts.map +1 -0
- package/dist/internal/widget.js +44 -0
- package/dist/internal/widget.js.map +1 -0
- package/dist/markdown/ast.d.ts +126 -0
- package/dist/markdown/ast.d.ts.map +1 -0
- package/dist/markdown/ast.js +8 -0
- package/dist/markdown/ast.js.map +1 -0
- package/dist/markdown/hx.d.ts +24 -0
- package/dist/markdown/hx.d.ts.map +1 -0
- package/dist/markdown/hx.js +25 -0
- package/dist/markdown/hx.js.map +1 -0
- package/dist/markdown/index.d.ts +90 -0
- package/dist/markdown/index.d.ts.map +1 -0
- package/dist/markdown/index.js +413 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/markdown/parse.d.ts +8 -0
- package/dist/markdown/parse.d.ts.map +1 -0
- package/dist/markdown/parse.js +911 -0
- package/dist/markdown/parse.js.map +1 -0
- package/dist/markdown/spans.d.ts +20 -0
- package/dist/markdown/spans.d.ts.map +1 -0
- package/dist/markdown/spans.js +96 -0
- package/dist/markdown/spans.js.map +1 -0
- package/dist/media-player/backends.d.ts +64 -0
- package/dist/media-player/backends.d.ts.map +1 -0
- package/dist/media-player/backends.js +110 -0
- package/dist/media-player/backends.js.map +1 -0
- package/dist/media-player/control.d.ts +40 -0
- package/dist/media-player/control.d.ts.map +1 -0
- package/dist/media-player/control.js +44 -0
- package/dist/media-player/control.js.map +1 -0
- package/dist/media-player/hx.d.ts +24 -0
- package/dist/media-player/hx.d.ts.map +1 -0
- package/dist/media-player/hx.js +25 -0
- package/dist/media-player/hx.js.map +1 -0
- package/dist/media-player/index.d.ts +107 -0
- package/dist/media-player/index.d.ts.map +1 -0
- package/dist/media-player/index.js +219 -0
- package/dist/media-player/index.js.map +1 -0
- package/dist/media-player/mpv.d.ts +4 -0
- package/dist/media-player/mpv.d.ts.map +1 -0
- package/dist/media-player/mpv.js +120 -0
- package/dist/media-player/mpv.js.map +1 -0
- package/dist/media-player/vlc.d.ts +8 -0
- package/dist/media-player/vlc.d.ts.map +1 -0
- package/dist/media-player/vlc.js +83 -0
- package/dist/media-player/vlc.js.map +1 -0
- package/dist/richtext/index.d.ts +19 -0
- package/dist/richtext/index.d.ts.map +1 -0
- package/dist/richtext/index.js +4 -0
- package/dist/richtext/index.js.map +1 -0
- package/dist/richtext/links.d.ts +12 -0
- package/dist/richtext/links.d.ts.map +1 -0
- package/dist/richtext/links.js +64 -0
- package/dist/richtext/links.js.map +1 -0
- package/dist/richtext/menu.d.ts +11 -0
- package/dist/richtext/menu.d.ts.map +1 -0
- package/dist/richtext/menu.js +43 -0
- package/dist/richtext/menu.js.map +1 -0
- package/dist/richtext/node.d.ts +151 -0
- package/dist/richtext/node.d.ts.map +1 -0
- package/dist/richtext/node.js +255 -0
- package/dist/richtext/node.js.map +1 -0
- package/dist/richtext/runs.d.ts +92 -0
- package/dist/richtext/runs.d.ts.map +1 -0
- package/dist/richtext/runs.js +158 -0
- package/dist/richtext/runs.js.map +1 -0
- package/dist/table/hx.d.ts +24 -0
- package/dist/table/hx.d.ts.map +1 -0
- package/dist/table/hx.js +25 -0
- package/dist/table/hx.js.map +1 -0
- package/dist/table/index.d.ts +169 -0
- package/dist/table/index.d.ts.map +1 -0
- package/dist/table/index.js +844 -0
- package/dist/table/index.js.map +1 -0
- package/dist/table/rows.d.ts +136 -0
- package/dist/table/rows.d.ts.map +1 -0
- package/dist/table/rows.js +146 -0
- package/dist/table/rows.js.map +1 -0
- package/dist/terminal/backends.d.ts +105 -0
- package/dist/terminal/backends.d.ts.map +1 -0
- package/dist/terminal/backends.js +185 -0
- package/dist/terminal/backends.js.map +1 -0
- package/dist/terminal/hx.d.ts +24 -0
- package/dist/terminal/hx.d.ts.map +1 -0
- package/dist/terminal/hx.js +25 -0
- package/dist/terminal/hx.js.map +1 -0
- package/dist/terminal/index.d.ts +160 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +344 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/title.d.ts +24 -0
- package/dist/terminal/title.d.ts.map +1 -0
- package/dist/terminal/title.js +129 -0
- package/dist/terminal/title.js.map +1 -0
- package/dist/terminal/vt/colors.d.ts +63 -0
- package/dist/terminal/vt/colors.d.ts.map +1 -0
- package/dist/terminal/vt/colors.js +203 -0
- package/dist/terminal/vt/colors.js.map +1 -0
- package/dist/terminal/vt/diff.d.ts +117 -0
- package/dist/terminal/vt/diff.d.ts.map +1 -0
- package/dist/terminal/vt/diff.js +358 -0
- package/dist/terminal/vt/diff.js.map +1 -0
- package/dist/terminal/vt/fonts.d.ts +92 -0
- package/dist/terminal/vt/fonts.d.ts.map +1 -0
- package/dist/terminal/vt/fonts.js +178 -0
- package/dist/terminal/vt/fonts.js.map +1 -0
- package/dist/terminal/vt/index.d.ts +78 -0
- package/dist/terminal/vt/index.d.ts.map +1 -0
- package/dist/terminal/vt/index.js +312 -0
- package/dist/terminal/vt/index.js.map +1 -0
- package/dist/terminal/vt/keys.d.ts +74 -0
- package/dist/terminal/vt/keys.d.ts.map +1 -0
- package/dist/terminal/vt/keys.js +309 -0
- package/dist/terminal/vt/keys.js.map +1 -0
- package/dist/terminal/vt/mouse.d.ts +44 -0
- package/dist/terminal/vt/mouse.d.ts.map +1 -0
- package/dist/terminal/vt/mouse.js +106 -0
- package/dist/terminal/vt/mouse.js.map +1 -0
- package/dist/terminal/vt/node.d.ts +246 -0
- package/dist/terminal/vt/node.d.ts.map +1 -0
- package/dist/terminal/vt/node.js +1068 -0
- package/dist/terminal/vt/node.js.map +1 -0
- package/dist/terminal/vt/pty.d.ts +81 -0
- package/dist/terminal/vt/pty.d.ts.map +1 -0
- package/dist/terminal/vt/pty.js +201 -0
- package/dist/terminal/vt/pty.js.map +1 -0
- package/dist/terminal/vt/renderer.d.ts +179 -0
- package/dist/terminal/vt/renderer.d.ts.map +1 -0
- package/dist/terminal/vt/renderer.js +357 -0
- package/dist/terminal/vt/renderer.js.map +1 -0
- package/dist/terminal/vt/timers.d.ts +6 -0
- package/dist/terminal/vt/timers.d.ts.map +1 -0
- package/dist/terminal/vt/timers.js +16 -0
- package/dist/terminal/vt/timers.js.map +1 -0
- package/dist/terminal/vt/xterm.d.ts +142 -0
- package/dist/terminal/vt/xterm.d.ts.map +1 -0
- package/dist/terminal/vt/xterm.js +32 -0
- package/dist/terminal/vt/xterm.js.map +1 -0
- package/dist/terminal-output/hx.d.ts +24 -0
- package/dist/terminal-output/hx.d.ts.map +1 -0
- package/dist/terminal-output/hx.js +25 -0
- package/dist/terminal-output/hx.js.map +1 -0
- package/dist/terminal-output/index.d.ts +92 -0
- package/dist/terminal-output/index.d.ts.map +1 -0
- package/dist/terminal-output/index.js +179 -0
- package/dist/terminal-output/index.js.map +1 -0
- package/dist/terminal-output/runs.d.ts +27 -0
- package/dist/terminal-output/runs.d.ts.map +1 -0
- package/dist/terminal-output/runs.js +66 -0
- package/dist/terminal-output/runs.js.map +1 -0
- package/dist/three/canvas.d.ts +46 -0
- package/dist/three/canvas.d.ts.map +1 -0
- package/dist/three/canvas.js +305 -0
- package/dist/three/canvas.js.map +1 -0
- package/dist/three/events.d.ts +64 -0
- package/dist/three/events.d.ts.map +1 -0
- package/dist/three/events.js +146 -0
- package/dist/three/events.js.map +1 -0
- package/dist/three/geometries.d.ts +89 -0
- package/dist/three/geometries.d.ts.map +1 -0
- package/dist/three/geometries.js +345 -0
- package/dist/three/geometries.js.map +1 -0
- package/dist/three/globals.d.ts +7 -0
- package/dist/three/globals.d.ts.map +1 -0
- package/dist/three/globals.js +20 -0
- package/dist/three/globals.js.map +1 -0
- package/dist/three/hx.d.ts +9 -0
- package/dist/three/hx.d.ts.map +1 -0
- package/dist/three/hx.js +10 -0
- package/dist/three/hx.js.map +1 -0
- package/dist/three/index.d.ts +22 -0
- package/dist/three/index.d.ts.map +1 -0
- package/dist/three/index.js +24 -0
- package/dist/three/index.js.map +1 -0
- package/dist/three/jsx-dev-runtime.d.ts +19 -0
- package/dist/three/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/three/jsx-dev-runtime.js +2 -0
- package/dist/three/jsx-dev-runtime.js.map +1 -0
- package/dist/three/jsx-runtime.d.ts +19 -0
- package/dist/three/jsx-runtime.d.ts.map +1 -0
- package/dist/three/jsx-runtime.js +2 -0
- package/dist/three/jsx-runtime.js.map +1 -0
- package/dist/three/jsx.d.ts +198 -0
- package/dist/three/jsx.d.ts.map +1 -0
- package/dist/three/jsx.js +2 -0
- package/dist/three/jsx.js.map +1 -0
- package/dist/three/materials.d.ts +125 -0
- package/dist/three/materials.d.ts.map +1 -0
- package/dist/three/materials.js +229 -0
- package/dist/three/materials.js.map +1 -0
- package/dist/three/math.d.ts +146 -0
- package/dist/three/math.d.ts.map +1 -0
- package/dist/three/math.js +464 -0
- package/dist/three/math.js.map +1 -0
- package/dist/three/objects.d.ts +185 -0
- package/dist/three/objects.d.ts.map +1 -0
- package/dist/three/objects.js +309 -0
- package/dist/three/objects.js.map +1 -0
- package/dist/three/passes.d.ts +54 -0
- package/dist/three/passes.d.ts.map +1 -0
- package/dist/three/passes.js +78 -0
- package/dist/three/passes.js.map +1 -0
- package/dist/three/postprocess.d.ts +85 -0
- package/dist/three/postprocess.d.ts.map +1 -0
- package/dist/three/postprocess.js +503 -0
- package/dist/three/postprocess.js.map +1 -0
- package/dist/three/raycast.d.ts +24 -0
- package/dist/three/raycast.d.ts.map +1 -0
- package/dist/three/raycast.js +138 -0
- package/dist/three/raycast.js.map +1 -0
- package/dist/three/reconciler.d.ts +48 -0
- package/dist/three/reconciler.d.ts.map +1 -0
- package/dist/three/reconciler.js +416 -0
- package/dist/three/reconciler.js.map +1 -0
- package/dist/three/renderer-direct.d.ts +102 -0
- package/dist/three/renderer-direct.d.ts.map +1 -0
- package/dist/three/renderer-direct.js +782 -0
- package/dist/three/renderer-direct.js.map +1 -0
- package/dist/three/renderer-indirect.d.ts +68 -0
- package/dist/three/renderer-indirect.d.ts.map +1 -0
- package/dist/three/renderer-indirect.js +438 -0
- package/dist/three/renderer-indirect.js.map +1 -0
- package/dist/three/store.d.ts +81 -0
- package/dist/three/store.d.ts.map +1 -0
- package/dist/three/store.js +110 -0
- package/dist/three/store.js.map +1 -0
- package/dist/timeline/hx.d.ts +18 -0
- package/dist/timeline/hx.d.ts.map +1 -0
- package/dist/timeline/hx.js +10 -0
- package/dist/timeline/hx.js.map +1 -0
- package/dist/timeline/index.d.ts +152 -0
- package/dist/timeline/index.d.ts.map +1 -0
- package/dist/timeline/index.js +383 -0
- package/dist/timeline/index.js.map +1 -0
- package/dist/tray-host/hx.d.ts +24 -0
- package/dist/tray-host/hx.d.ts.map +1 -0
- package/dist/tray-host/hx.js +25 -0
- package/dist/tray-host/hx.js.map +1 -0
- package/dist/tray-host/index.d.ts +110 -0
- package/dist/tray-host/index.d.ts.map +1 -0
- package/dist/tray-host/index.js +191 -0
- package/dist/tray-host/index.js.map +1 -0
- package/dist/tray-host/manager.d.ts +137 -0
- package/dist/tray-host/manager.d.ts.map +1 -0
- package/dist/tray-host/manager.js +462 -0
- package/dist/tray-host/manager.js.map +1 -0
- package/dist/tray-host/notify.d.ts +22 -0
- package/dist/tray-host/notify.d.ts.map +1 -0
- package/dist/tray-host/notify.js +74 -0
- package/dist/tray-host/notify.js.map +1 -0
- package/dist/tray-host/protocol.d.ts +106 -0
- package/dist/tray-host/protocol.d.ts.map +1 -0
- package/dist/tray-host/protocol.js +191 -0
- package/dist/tray-host/protocol.js.map +1 -0
- package/dist/tree/hx.d.ts +24 -0
- package/dist/tree/hx.d.ts.map +1 -0
- package/dist/tree/hx.js +25 -0
- package/dist/tree/hx.js.map +1 -0
- package/dist/tree/index.d.ts +221 -0
- package/dist/tree/index.d.ts.map +1 -0
- package/dist/tree/index.js +716 -0
- package/dist/tree/index.js.map +1 -0
- package/dist/tree/internal.d.ts +18 -0
- package/dist/tree/internal.d.ts.map +1 -0
- package/dist/tree/internal.js +66 -0
- package/dist/tree/internal.js.map +1 -0
- package/dist/tree/rows.d.ts +177 -0
- package/dist/tree/rows.d.ts.map +1 -0
- package/dist/tree/rows.js +179 -0
- package/dist/tree/rows.js.map +1 -0
- package/package.json +166 -12
- package/src/ansi/cast.ts +159 -0
- package/src/ansi/index.ts +53 -0
- package/src/ansi/palette.ts +226 -0
- package/src/ansi/parse.ts +780 -0
- package/src/ansi/sgr.ts +380 -0
- package/src/ansi/utf8.ts +84 -0
- package/src/calendar/Calendar.ts +744 -0
- package/src/calendar/DatePicker.ts +368 -0
- package/src/calendar/dates.ts +307 -0
- package/src/calendar/index.ts +51 -0
- package/src/charts/components.ts +864 -0
- package/src/charts/data.ts +776 -0
- package/src/charts/hx.ts +39 -0
- package/src/charts/index.ts +99 -0
- package/src/charts/node.ts +932 -0
- package/src/charts/render.ts +982 -0
- package/src/charts/scale.ts +214 -0
- package/src/charts/spec.ts +122 -0
- package/src/charts/timers.ts +24 -0
- package/src/code/hx.ts +51 -0
- package/src/code/index.ts +174 -0
- package/src/code-editor/completion.ts +161 -0
- package/src/code-editor/doc.ts +198 -0
- package/src/code-editor/hx.ts +26 -0
- package/src/code-editor/index.ts +615 -0
- package/src/code-editor/node.ts +1926 -0
- package/src/code-language/hljs.ts +302 -0
- package/src/code-language/index.ts +51 -0
- package/src/code-language/languages/glsl.ts +120 -0
- package/src/code-language/languages/javascript.ts +419 -0
- package/src/code-language/languages/json.ts +72 -0
- package/src/code-language/languages/shell.ts +221 -0
- package/src/code-language/languages/sql.ts +165 -0
- package/src/code-language/lezer.ts +190 -0
- package/src/code-language/registry.ts +66 -0
- package/src/code-language/runs.ts +128 -0
- package/src/code-language/stream.ts +306 -0
- package/src/code-language/textmate.ts +134 -0
- package/src/code-language/theme.ts +124 -0
- package/src/code-language/timers.ts +36 -0
- package/src/code-language/types.ts +252 -0
- package/src/codeblock/index.ts +146 -0
- package/src/color-picker/ColorField.ts +333 -0
- package/src/color-picker/ColorPicker.ts +1069 -0
- package/src/color-picker/color.ts +399 -0
- package/src/color-picker/index.ts +50 -0
- package/src/desktop-calendar/eds.ts +484 -0
- package/src/desktop-calendar/ical.ts +119 -0
- package/src/desktop-calendar/index.ts +287 -0
- package/src/embed/client.ts +311 -0
- package/src/embed/host.ts +432 -0
- package/src/embed/index.ts +33 -0
- package/src/embed/timers.ts +32 -0
- package/src/flow/draw.ts +418 -0
- package/src/flow/index.ts +473 -0
- package/src/flow/model.ts +687 -0
- package/src/flow/node.ts +3694 -0
- package/src/flow/paths.ts +403 -0
- package/src/flow/types.ts +634 -0
- package/src/formula/hx.ts +51 -0
- package/src/formula/index.ts +243 -0
- package/src/formula/katex.ts +209 -0
- package/src/formula/layout.ts +876 -0
- package/src/formula/node.ts +467 -0
- package/src/html/controls.ts +244 -0
- package/src/html/css/cascade.ts +606 -0
- package/src/html/css/parse.ts +500 -0
- package/src/html/css/style.ts +1371 -0
- package/src/html/css/ua.ts +174 -0
- package/src/html/css/values.ts +358 -0
- package/src/html/dom.ts +410 -0
- package/src/html/hx.ts +55 -0
- package/src/html/index.ts +545 -0
- package/src/html/layout/block.ts +876 -0
- package/src/html/layout/boxes.ts +981 -0
- package/src/html/layout/flex.ts +297 -0
- package/src/html/layout/floats.ts +125 -0
- package/src/html/layout/inline.ts +870 -0
- package/src/html/layout/table.ts +380 -0
- package/src/html/node.ts +967 -0
- package/src/html/paint.ts +605 -0
- package/src/html/resources.ts +214 -0
- package/src/index.ts +638 -0
- package/src/internal/heights.ts +211 -0
- package/src/internal/hx.ts +53 -0
- package/src/internal/text.ts +44 -0
- package/src/internal/timers.ts +44 -0
- package/src/internal/widget.ts +92 -0
- package/src/markdown/ast.ts +163 -0
- package/src/markdown/hx.ts +51 -0
- package/src/markdown/index.ts +686 -0
- package/src/markdown/parse.ts +1037 -0
- package/src/markdown/spans.ts +143 -0
- package/src/media-player/backends.ts +155 -0
- package/src/media-player/control.ts +70 -0
- package/src/media-player/hx.ts +51 -0
- package/src/media-player/index.ts +378 -0
- package/src/media-player/mpv.ts +146 -0
- package/src/media-player/vlc.ts +97 -0
- package/src/richtext/index.ts +42 -0
- package/src/richtext/links.ts +78 -0
- package/src/richtext/menu.ts +49 -0
- package/src/richtext/node.ts +406 -0
- package/src/richtext/runs.ts +253 -0
- package/src/table/hx.ts +51 -0
- package/src/table/index.ts +1219 -0
- package/src/table/rows.ts +275 -0
- package/src/terminal/backends.ts +242 -0
- package/src/terminal/hx.ts +51 -0
- package/src/terminal/index.ts +574 -0
- package/src/terminal/title.ts +172 -0
- package/src/terminal/vt/colors.ts +247 -0
- package/src/terminal/vt/diff.ts +467 -0
- package/src/terminal/vt/fonts.ts +233 -0
- package/src/terminal/vt/index.ts +443 -0
- package/src/terminal/vt/keys.ts +369 -0
- package/src/terminal/vt/mouse.ts +144 -0
- package/src/terminal/vt/node.ts +1242 -0
- package/src/terminal/vt/pty.ts +334 -0
- package/src/terminal/vt/renderer.ts +555 -0
- package/src/terminal/vt/timers.ts +31 -0
- package/src/terminal/vt/xterm.ts +193 -0
- package/src/terminal-output/hx.ts +51 -0
- package/src/terminal-output/index.ts +340 -0
- package/src/terminal-output/runs.ts +79 -0
- package/src/three/canvas.ts +451 -0
- package/src/three/events.ts +197 -0
- package/src/three/geometries.ts +429 -0
- package/src/three/globals.ts +34 -0
- package/src/three/hx.ts +22 -0
- package/src/three/index.ts +98 -0
- package/src/three/jsx-dev-runtime.ts +27 -0
- package/src/three/jsx-runtime.ts +38 -0
- package/src/three/jsx.ts +275 -0
- package/src/three/materials.ts +270 -0
- package/src/three/math.ts +585 -0
- package/src/three/objects.ts +397 -0
- package/src/three/passes.ts +90 -0
- package/src/three/postprocess.ts +677 -0
- package/src/three/raycast.ts +189 -0
- package/src/three/react-reconciler.d.ts +50 -0
- package/src/three/reconciler.ts +624 -0
- package/src/three/renderer-direct.ts +1055 -0
- package/src/three/renderer-indirect.ts +570 -0
- package/src/three/store.ts +207 -0
- package/src/timeline/hx.ts +31 -0
- package/src/timeline/index.ts +603 -0
- package/src/tray-host/hx.ts +51 -0
- package/src/tray-host/index.ts +331 -0
- package/src/tray-host/manager.ts +639 -0
- package/src/tray-host/notify.ts +102 -0
- package/src/tray-host/protocol.ts +235 -0
- package/src/tree/hx.ts +51 -0
- package/src/tree/index.ts +1087 -0
- package/src/tree/internal.ts +87 -0
- package/src/tree/rows.ts +334 -0
- package/src/index.d.ts +0 -2
- package/src/index.js +0 -9
- package/src/sparkline/index.d.ts +0 -29
- package/src/sparkline/index.js +0 -50
- package/src/sparkline/node.js +0 -72
package/README.md
CHANGED
|
@@ -7,10 +7,14 @@ Everything here is built on react-x11's public API — the built-in host
|
|
|
7
7
|
elements, or the `registerElement` seam in `react-x11/host`. Nothing here
|
|
8
8
|
needs a change to core to exist, and core does not grow to carry it.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
**[Documentation](https://sidorares.github.io/react-x11-components/)** — one
|
|
11
|
+
reference page per component, rendered from [`docs/`](docs/README.md). This
|
|
12
|
+
README is the tour; that is the detail.
|
|
13
|
+
|
|
14
|
+
> **Installable now.** react-x11 2.0.0 is on npm, so the peer range this
|
|
15
|
+
> package declares resolves and `npm install` just works. The published
|
|
16
|
+
> release is `0.1.0`; `master` carries components added since, so use a
|
|
17
|
+
> checkout if you want what is not in that release yet.
|
|
14
18
|
|
|
15
19
|
## What is here, and what is in core
|
|
16
20
|
|
|
@@ -40,27 +44,29 @@ and it belongs here.
|
|
|
40
44
|
## Install
|
|
41
45
|
|
|
42
46
|
```bash
|
|
43
|
-
npm install @react-x11/components
|
|
47
|
+
npm install @react-x11/components react react-x11
|
|
44
48
|
```
|
|
45
49
|
|
|
46
50
|
`react` and `react-x11` are peer dependencies — deliberately. Registering a
|
|
47
51
|
host element mutates state inside react-x11, so a second copy of the renderer
|
|
48
52
|
would leave you with an element that lays out correctly and never paints.
|
|
49
53
|
|
|
54
|
+
Core must be **2.0.0 or newer**: that is the release the subpaths this
|
|
55
|
+
package imports (`react-x11/host`, `/node`, `/style`) arrived in.
|
|
56
|
+
|
|
50
57
|
## Usage
|
|
51
58
|
|
|
52
59
|
```jsx
|
|
53
|
-
import {
|
|
60
|
+
import { Code } from '@react-x11/components';
|
|
54
61
|
|
|
55
62
|
function App() {
|
|
56
63
|
return (
|
|
57
|
-
<window width={
|
|
64
|
+
<window width={480} height={240} title="components">
|
|
58
65
|
<box style={{ flexGrow: 1, padding: 16 }}>
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
style={{ width: 320, height: 80 }}
|
|
66
|
+
<Code
|
|
67
|
+
source={'const x = 1;\nconsole.log(x);\n'}
|
|
68
|
+
lang="ts"
|
|
69
|
+
lineNumbers
|
|
64
70
|
/>
|
|
65
71
|
</box>
|
|
66
72
|
</window>
|
|
@@ -81,26 +87,978 @@ this repo, not an aspiration.
|
|
|
81
87
|
Deep imports work too, for apps without a bundler:
|
|
82
88
|
|
|
83
89
|
```js
|
|
84
|
-
import {
|
|
90
|
+
import { Code } from '@react-x11/components/code';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## TypeScript
|
|
94
|
+
|
|
95
|
+
The package is written in TypeScript and ships its own declarations, so
|
|
96
|
+
there is no `@types` package to install. Point your compiler at react-x11's
|
|
97
|
+
JSX namespace and the host elements type-check:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"compilerOptions": {
|
|
102
|
+
"jsx": "react-jsx",
|
|
103
|
+
"jsxImportSource": "react-x11"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Importing a component teaches JSX its element too, so `<codeeditor>` is a
|
|
109
|
+
typed tag as soon as `CodeEditor` is in scope. Props types are exported
|
|
110
|
+
under their component's name:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import type { CodeEditorProps } from '@react-x11/components';
|
|
85
114
|
```
|
|
86
115
|
|
|
87
116
|
## Components
|
|
88
117
|
|
|
89
|
-
| Component
|
|
90
|
-
|
|
|
91
|
-
| `
|
|
118
|
+
| Component | Import | |
|
|
119
|
+
| ---------------- | ---------------------------------------- | ------------------------------------------------------------ |
|
|
120
|
+
| `Calendar` | `@react-x11/components/calendar` | A month grid: one date or a range, any day blockable. |
|
|
121
|
+
| `DatePicker` | `@react-x11/components/calendar` | That calendar on a popup, behind a field. |
|
|
122
|
+
| `LineChart` … | `@react-x11/components/charts` | Cartesian charts; a million points is a normal input. |
|
|
123
|
+
| `ColorPicker` … | `@react-x11/components/color-picker` | A colour input: field, hue, alpha, swatches, eyedropper. |
|
|
124
|
+
| `Code` | `@react-x11/components/code` | A static code block: highlighted, selectable. |
|
|
125
|
+
| `CodeEditor` | `@react-x11/components/code-editor` | Multiline code editing: highlighting, completion. |
|
|
126
|
+
| `Flow` | `@react-x11/components/flow` | A directed-graph editor: nodes, edges, pan and zoom. |
|
|
127
|
+
| `Html` | `@react-x11/components/html` | A static HTML + CSS document, selectable, with seams. |
|
|
128
|
+
| `Markdown` | `@react-x11/components/markdown` | Streaming-friendly GFM with cross-block selection. |
|
|
129
|
+
| `MediaPlayer` | `@react-x11/components/media-player` | mpv or VLC, embedded, with real transport control. |
|
|
130
|
+
| `Table` | `@react-x11/components/table` | A data table: sortable, virtualized, any row height. |
|
|
131
|
+
| `Terminal` | `@react-x11/components/terminal` | A real terminal: an embedded emulator, or its own. |
|
|
132
|
+
| `TerminalOutput` | `@react-x11/components/terminal-output` | A captured session, rendered. `<Terminal>`'s static sibling. |
|
|
133
|
+
| `Timeline` … | `@react-x11/components/timeline` | A run of events: a mark per step, a line between. |
|
|
134
|
+
| `TrayHost` | `@react-x11/components/tray-host` | The system tray: applications dock their icons in. |
|
|
135
|
+
| `Tree` | `@react-x11/components/tree` | A disclosure tree: seams throughout, and virtualized. |
|
|
136
|
+
| _(hook)_ | `@react-x11/components/desktop-calendar` | The user's real calendar events, over D-Bus. |
|
|
137
|
+
|
|
138
|
+
Five shared modules sit underneath and are importable on their own:
|
|
139
|
+
`/richtext` (the styled-text element a document selects across),
|
|
140
|
+
`/codeblock` (the look of a block of code, shared by `<Code>` and
|
|
141
|
+
`<Markdown>`'s fences), `/code-language` (the pluggable tokenizer seam,
|
|
142
|
+
the built-in languages and the token palettes), `/ansi` (a captured
|
|
143
|
+
terminal session reduced to a document of styled spans) and `/embed` (the
|
|
144
|
+
spawn, watch and hand-back lifecycle both XEmbed wrappers are built on).
|
|
145
|
+
|
|
146
|
+
Selecting text is **core's**, not this package's: a `<box selectable>` is
|
|
147
|
+
a surface, everything under it that answers for its own text is in the
|
|
148
|
+
selection, and the drag, the word and block granularities, Ctrl+A, Ctrl+C
|
|
149
|
+
and PRIMARY come with it (react-x11#291). `<Markdown>` and `<Code>` set
|
|
150
|
+
that prop and say which parts are chrome; the elements underneath answer
|
|
151
|
+
`textContent`/`textIndexAt`/`textCaretRect`/`textRangeRects`, which is all
|
|
152
|
+
an element of your own has to do to join a document.
|
|
153
|
+
|
|
154
|
+
## Charts
|
|
155
|
+
|
|
156
|
+
A [shadcn/charts](https://ui.shadcn.com/charts)-shaped component set for
|
|
157
|
+
cartesian charts — line, area, bar, scatter — with the composition you
|
|
158
|
+
expect and a cost model you usually do not: **every frame is bounded by
|
|
159
|
+
pixels, never by points.**
|
|
160
|
+
|
|
161
|
+
```jsx
|
|
162
|
+
import {
|
|
163
|
+
ChartContainer,
|
|
164
|
+
LineChart,
|
|
165
|
+
LineSeries,
|
|
166
|
+
XAxis,
|
|
167
|
+
YAxis,
|
|
168
|
+
CartesianGrid,
|
|
169
|
+
ChartTooltip,
|
|
170
|
+
ChartLegend,
|
|
171
|
+
} from '@react-x11/components/charts';
|
|
172
|
+
|
|
173
|
+
const config = {
|
|
174
|
+
cpu: { label: 'CPU', color: '$accent' },
|
|
175
|
+
mem: { label: 'Memory', color: '#e17055' },
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
<ChartContainer config={config} style={{ height: 240 }}>
|
|
179
|
+
<LineChart data={rows}>
|
|
180
|
+
<CartesianGrid />
|
|
181
|
+
<XAxis dataKey="time" type="time" />
|
|
182
|
+
<YAxis />
|
|
183
|
+
<LineSeries dataKey="cpu" />
|
|
184
|
+
<LineSeries dataKey="mem" curve="monotone" />
|
|
185
|
+
<ChartTooltip />
|
|
186
|
+
<ChartLegend />
|
|
187
|
+
</LineChart>
|
|
188
|
+
</ChartContainer>;
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The children are config carriers, recharts-style; one registered element
|
|
192
|
+
paints the grid, the axes and every series in a single pass. `data` takes
|
|
193
|
+
rows (shadcn-familiar), columns (`{ length, columns }` of typed arrays —
|
|
194
|
+
the fast path), or a `ChartData` streaming store whose appends extend the
|
|
195
|
+
decimation index incrementally and never rescan. A live feed should window
|
|
196
|
+
by **time**, not only by count: `maxAge: { key: 't', ms: 60_000 }` keeps
|
|
197
|
+
"the last minute", where a count window silently means "however long that
|
|
198
|
+
many points took" — an OS throttling a hidden window's timers leaves a
|
|
199
|
+
minutes-wide, points-thin era that a count window then renders as fresh
|
|
200
|
+
data squeezed into a sliver. Age eviction drops it on the first append
|
|
201
|
+
after resume, hard stalls included; `ChartData.clear()` is the manual
|
|
202
|
+
reset for switching feeds.
|
|
203
|
+
|
|
204
|
+
Pan and zoom are a controlled domain: pass `<XAxis domain={[a, b]}>` from
|
|
205
|
+
app state, and use `plotRef` — the imperative snap query the tooltip
|
|
206
|
+
itself uses — to convert a drag's pixels into domain units (the hit
|
|
207
|
+
carries the plot rect and the x value under any window x). The demo's
|
|
208
|
+
million-point chart pans by drag and zooms by buttons this way; the
|
|
209
|
+
pyramid keeps every frame O(width) at any zoom.
|
|
210
|
+
|
|
211
|
+
What "put a lot of effort into performance" means here, concretely:
|
|
212
|
+
|
|
213
|
+
- **Off the viewport costs nothing.** Core already culls the paint of
|
|
214
|
+
scrolled-away nodes; a `ChartData` append to a fully offscreen chart
|
|
215
|
+
skips even the invalidation — scrolling back repaints from current data.
|
|
216
|
+
- **Too small to see costs nothing to draw.** Every series renders through
|
|
217
|
+
a per-pixel-column min/max index (a pyramid over the data, built lazily
|
|
218
|
+
and extended on append), so a million points in a 90px cell cost ~90
|
|
219
|
+
rectangles. A million points that fall on one pixel render one pixel.
|
|
220
|
+
- **Server-side drawing commands by default, pixels when they win.** A
|
|
221
|
+
dense line goes out as one batched `FillRectangles` (~8 bytes per pixel
|
|
222
|
+
column); a sparse one as a real antialiased path. The one place a pixel
|
|
223
|
+
push wins — a scatter covering most of the plot — is detected by
|
|
224
|
+
comparing the actual byte costs, and flips to one composited density
|
|
225
|
+
image.
|
|
226
|
+
|
|
227
|
+
Tooltips snap to the nearest point in O(log n) through a ref into the
|
|
228
|
+
element. **The value bubble is a real popup window by default** — anchored
|
|
229
|
+
to the data point through core's anchor system, stacked above everything
|
|
230
|
+
(content that flows after the chart included), flipped at screen edges,
|
|
231
|
+
never focused. `<ChartTooltip mode="overlay">` keeps it as a
|
|
232
|
+
hit-transparent box inside the chart instead — one window, one paint
|
|
233
|
+
surface — with the documented trade that later siblings can overdraw
|
|
234
|
+
whatever part of it would have left the chart's box. The crosshair and
|
|
235
|
+
point markers are part of the plot and stay in-window either way, and the
|
|
236
|
+
hover's React re-render contributes no damage of its own. Pass
|
|
237
|
+
`onFrameStats` to see
|
|
238
|
+
what any frame cost: per-series mode, commands issued, estimated wire
|
|
239
|
+
bytes, prep and paint time. `npm run examples:charts` is a live tour —
|
|
240
|
+
streaming at 60 points/s, a million-point walk, small multiples, stacked
|
|
241
|
+
bars and areas, a 200k-point density scatter — with that HUD under every
|
|
242
|
+
chart. [`docs/prd-charts.md`](docs/prd-charts.md) is the design record.
|
|
243
|
+
|
|
244
|
+
Pie/radial charts and a second y axis are deliberately not in this first
|
|
245
|
+
cut; the cartesian perf story is.
|
|
246
|
+
|
|
247
|
+
## Markdown
|
|
248
|
+
|
|
249
|
+
A GFM renderer built for streamed model output — the
|
|
250
|
+
[Streamdown](https://streamdown.ai/) use case, rendered natively. Feed it a
|
|
251
|
+
growing `source` and every instant renders clean: unclosed `**bold`,
|
|
252
|
+
`` `code `` or a half-arrived `[link](…` never flash their raw markers, an
|
|
253
|
+
ambiguous `---` tail is held until it can be read, an open fence is already
|
|
254
|
+
a code block. When the stream ends, flip `partial` off.
|
|
255
|
+
|
|
256
|
+
```jsx
|
|
257
|
+
import { Markdown } from '@react-x11/components/markdown';
|
|
258
|
+
|
|
259
|
+
<box style={{ overflow: 'scroll', flexGrow: 1 }}>
|
|
260
|
+
<Markdown
|
|
261
|
+
source={streamed}
|
|
262
|
+
partial={stillStreaming}
|
|
263
|
+
onLink={(href) => open(href)}
|
|
264
|
+
style={{ padding: 16 }}
|
|
265
|
+
/>
|
|
266
|
+
</box>;
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The feature set is GFM: headings (ATX and setext), emphasis with the real
|
|
270
|
+
CommonMark delimiter algorithm, inline code, links and autolinks, images
|
|
271
|
+
(rendered as their alt text, linked to the source — no remote fetches),
|
|
272
|
+
nested and task lists, blockquotes, tables with alignment and measured
|
|
273
|
+
column widths, thematic breaks, fenced code highlighted through the same
|
|
274
|
+
language seam as `<CodeEditor>` (`resolveLanguage` is where tags the
|
|
275
|
+
built-ins do not cover come from — `hljsLanguage` wraps highlight.js). The parser is this package's own — no
|
|
276
|
+
markdown→HTML pass anywhere — and is exported (`parseMarkdown`) with the
|
|
277
|
+
AST types.
|
|
278
|
+
|
|
279
|
+
**Selection is the point.** Text selects across every block — drag,
|
|
280
|
+
double-click a word, triple-click a block, Ctrl+A, Ctrl+C — and a mouse-up
|
|
281
|
+
with a selection takes the X11 PRIMARY selection, so middle-click paste
|
|
282
|
+
works everywhere. All of that is core's `selectable` (react-x11#291); what
|
|
283
|
+
this component adds is which parts are chrome, so copied text is clean:
|
|
284
|
+
list markers stay behind, and the separators come from the layout, which
|
|
285
|
+
for a table is exactly cells with tabs and rows with newlines. Rendering is cached
|
|
286
|
+
per top-level block on the raw source text, so appending to the tail
|
|
287
|
+
re-renders the tail alone. `npm run examples:markdown` streams a document
|
|
288
|
+
in live.
|
|
289
|
+
|
|
290
|
+
MDX is on the roadmap, not in the box: the AST reserves a `component` node
|
|
291
|
+
and the renderer is ordinary React composition, so user components can
|
|
292
|
+
interleave — including mid-stream — once the parser learns the syntax.
|
|
293
|
+
|
|
294
|
+
## HTML
|
|
295
|
+
|
|
296
|
+
```jsx
|
|
297
|
+
import { Html } from '@react-x11/components/html';
|
|
298
|
+
|
|
299
|
+
<box style={{ overflow: 'scroll', flexGrow: 1 }}>
|
|
300
|
+
<Html
|
|
301
|
+
source={html}
|
|
302
|
+
partial={false}
|
|
303
|
+
onLink={(href) => openInBrowser(href)}
|
|
304
|
+
onResource={(r) => (r.kind === 'image' ? readImage(r.url) : null)}
|
|
305
|
+
/>
|
|
306
|
+
</box>;
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
A document an application is _handed_ — mail, release notes, a help page, an
|
|
310
|
+
exported report — rendered with selectable text and real widgets for its form
|
|
311
|
+
controls. Block flow with margin collapsing, an inline formatting context
|
|
312
|
+
with full shaping and bidi, floats, lists, tables and positioning are this
|
|
313
|
+
package's; `display: flex` is Yoga's, which is already in the process.
|
|
314
|
+
|
|
315
|
+
**Nothing is fetched and nothing is executed**, and neither is a setting.
|
|
316
|
+
`onResource` is asked for every `<img>`, `<link rel=stylesheet>` and
|
|
317
|
+
`@import` — absent, images draw a frame at their attribute size and linked
|
|
318
|
+
sheets are skipped. `onScript` is handed a `<script>`'s type, `src` and text
|
|
319
|
+
verbatim; there is no parser and no sandbox, because a renderer that
|
|
320
|
+
half-runs a script is one nobody can reason about. An application that wants
|
|
321
|
+
scripting brings an engine and drives the result through the DOM handle.
|
|
322
|
+
|
|
323
|
+
The form controls are the point where this differs from every HTML widget
|
|
324
|
+
that came before it here: a `<select>` in a document drops the same menu as a
|
|
325
|
+
`<Select>` in the window around it, because it **is** one. They mount as
|
|
326
|
+
positioned siblings of the element at the rectangles layout reserved — the
|
|
327
|
+
escape hatch `<Flow>` opened for a node whose body is a form.
|
|
328
|
+
|
|
329
|
+
Unlike every other document surface in this package, `<Html>` **draws** the
|
|
330
|
+
document rather than composing it from `<box>` and `<richtext>`. Partly for
|
|
331
|
+
cost — a document is thousands of elements — but mainly because CSS layout is
|
|
332
|
+
not the host's layout: block flow, floats and table column sizing are not
|
|
333
|
+
flexbox, and composing would mean approximating the model. What it reuses
|
|
334
|
+
from `/richtext` is everything that was never about the element — the
|
|
335
|
+
`TextRun` vocabulary, the per-run decoration painter, the bidi-correct
|
|
336
|
+
selection bands.
|
|
337
|
+
|
|
338
|
+
`handle.document` is the live DOM ([domhandler]'s tree, which [domutils]
|
|
339
|
+
speaks); mutate it and call `handle.refresh()`. That is explicit rather than
|
|
340
|
+
observed on purpose: watching a plain object graph costs a proxy per node,
|
|
341
|
+
and the budget went on the static render instead. `npm run examples:html`
|
|
342
|
+
drives both seams for real.
|
|
343
|
+
|
|
344
|
+
[domhandler]: https://github.com/fb55/domhandler
|
|
345
|
+
[domutils]: https://github.com/fb55/domutils
|
|
346
|
+
|
|
347
|
+
## Code
|
|
348
|
+
|
|
349
|
+
The static sibling of `<CodeEditor>`: a read-only, selectable code block
|
|
350
|
+
for showing code rather than editing it.
|
|
351
|
+
|
|
352
|
+
```jsx
|
|
353
|
+
import { Code } from '@react-x11/components/code';
|
|
354
|
+
|
|
355
|
+
<Code source={snippet} lang="ts" lineNumbers />;
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Highlighting goes through the same language seam (`lang` tag or an
|
|
359
|
+
explicit `language={…}`) and the look is shared with `<Markdown>`'s fenced
|
|
360
|
+
blocks, so the two agree in one window. Selection and copy are core's; the
|
|
361
|
+
line-number gutter is `selectable={false}`, so copied code pastes clean.
|
|
362
|
+
|
|
363
|
+
## A terminal session you already have: `<TerminalOutput>`
|
|
364
|
+
|
|
365
|
+
The static sibling of `<Terminal>`, exactly as `<Code>` is `<CodeEditor>`'s.
|
|
366
|
+
You ran something in a pty somewhere and kept the bytes; this draws what the
|
|
367
|
+
terminal would have drawn, with no pty, no process and no input.
|
|
368
|
+
|
|
369
|
+
```jsx
|
|
370
|
+
import { TerminalOutput } from '@react-x11/components/terminal-output';
|
|
371
|
+
|
|
372
|
+
<TerminalOutput data={await readFile('build.log')} lineNumbers />;
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**A log is a document, not a grid**, and that is the whole design. A build
|
|
376
|
+
log has lines, not rows, and no column count of its own — so it renders as
|
|
377
|
+
styled spans in one `<richtext>`, which wraps if you ask, flows in a page,
|
|
378
|
+
and selects like any other block. Putting it on a fixed grid would mean
|
|
379
|
+
inventing a `cols` the capture never had and then wrapping at it.
|
|
380
|
+
|
|
381
|
+
`\r` is honoured, which is most of the value: every progress bar and
|
|
382
|
+
`npm install` line is a carriage return plus an overwrite, and a renderer
|
|
383
|
+
that reads `\r` as a newline turns a three-line install into nine hundred.
|
|
384
|
+
So are SGR in full (the 256 cube, truecolor, and the `:` sub-parameter forms,
|
|
385
|
+
so `4:3` curly underlines and `58` underline colours work), `\e[K`, the
|
|
386
|
+
in-line cursor moves, and **OSC 8 hyperlinks** — which `cargo`, `gcc` and
|
|
387
|
+
`ls --hyperlink` all emit, and which arrive clickable through `onLink`.
|
|
388
|
+
|
|
389
|
+
A capture from a full-screen program (vim, htop) is a different animal: those
|
|
390
|
+
bytes address the cursor and mean nothing except at the grid they were made
|
|
391
|
+
at. **That case is not rendered faithfully yet, and the component says so**
|
|
392
|
+
rather than guessing — `onDocument` hands over a document whose `needsScreen`
|
|
393
|
+
is true, with `dropped` naming every sequence that went unhonoured and how
|
|
394
|
+
often. A real cell-grid renderer for it is phase 2 in
|
|
395
|
+
[`docs/prd-terminal-output.md`](docs/prd-terminal-output.md), which is the
|
|
396
|
+
design record.
|
|
397
|
+
|
|
398
|
+
The parser is its own dependency-free shared module and is useful without a
|
|
399
|
+
terminal in sight:
|
|
400
|
+
|
|
401
|
+
```js
|
|
402
|
+
import {
|
|
403
|
+
parseAnsi,
|
|
404
|
+
stripAnsi,
|
|
405
|
+
parseCast,
|
|
406
|
+
castOutput,
|
|
407
|
+
} from '@react-x11/components/ansi';
|
|
408
|
+
|
|
409
|
+
stripAnsi(log); // the text, escapes resolved away
|
|
410
|
+
parseAnsi(log).lines[0].spans; // colour kept as intent: { kind: 'ansi', index: 2 }
|
|
411
|
+
parseAnsi(castOutput(parseCast(rec), { until: 12.5 })); // an asciinema still
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Colour stays **intent** through the parse and resolves at paint, which is
|
|
415
|
+
what lets one parsed capture render correctly against a light theme and a
|
|
416
|
+
dark one. `npm run examples:terminal-output` is a test run, a progress bar, a
|
|
417
|
+
compiler capture with live hyperlinks, and a vim session reporting what it
|
|
418
|
+
needed.
|
|
419
|
+
|
|
420
|
+
## Timeline
|
|
421
|
+
|
|
422
|
+
A vertical run of events — a delivery, a deploy, an audit log, a wizard's
|
|
423
|
+
progress. The API is
|
|
424
|
+
[Chakra UI's Timeline](https://chakra-ui.com/docs/components/timeline) with
|
|
425
|
+
its parts spelled flat, so `Timeline.Root` is `<Timeline>` and a snippet
|
|
426
|
+
copied from their docs is otherwise the same tree:
|
|
427
|
+
|
|
428
|
+
```jsx
|
|
429
|
+
import {
|
|
430
|
+
Timeline,
|
|
431
|
+
TimelineItem,
|
|
432
|
+
TimelineConnector,
|
|
433
|
+
TimelineSeparator,
|
|
434
|
+
TimelineIndicator,
|
|
435
|
+
TimelineContent,
|
|
436
|
+
TimelineTitle,
|
|
437
|
+
TimelineDescription,
|
|
438
|
+
} from '@react-x11/components/timeline';
|
|
439
|
+
|
|
440
|
+
<Timeline variant="outline" size="lg">
|
|
441
|
+
<TimelineItem>
|
|
442
|
+
<TimelineConnector>
|
|
443
|
+
<TimelineSeparator />
|
|
444
|
+
<TimelineIndicator accent="$success">
|
|
445
|
+
<Icon name="check" size={12} />
|
|
446
|
+
</TimelineIndicator>
|
|
447
|
+
</TimelineConnector>
|
|
448
|
+
<TimelineContent>
|
|
449
|
+
<TimelineTitle>Product shipped</TimelineTitle>
|
|
450
|
+
<TimelineDescription>13th May 2021</TimelineDescription>
|
|
451
|
+
</TimelineContent>
|
|
452
|
+
</TimelineItem>
|
|
453
|
+
</Timeline>;
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
It registers no element: a timeline is `<box>` and `<text>`, and the line
|
|
457
|
+
down the gutter is one absolutely-positioned pixel spanning the item — so
|
|
458
|
+
its length is a consequence of the content beside it rather than a height
|
|
459
|
+
anyone has to name. `npm run examples:timeline` runs a live release
|
|
460
|
+
pipeline beside galleries of the sizes and variants;
|
|
461
|
+
[the reference](docs/components/timeline.md) has the rest, including why
|
|
462
|
+
every indicator's chip is opaque.
|
|
463
|
+
|
|
464
|
+
## The disclosure tree
|
|
465
|
+
|
|
466
|
+
`<Tree>` is a **successor to react-x11's own `<Tree>`, which core is
|
|
467
|
+
retiring** — nothing here imports it, and the two share no code. What it
|
|
468
|
+
keeps is the behaviour a user has already learnt: the keyboard map,
|
|
469
|
+
type-ahead, and the twisty being its own hit target, so peeking into a folder
|
|
470
|
+
does not select it.
|
|
471
|
+
|
|
472
|
+
```jsx
|
|
473
|
+
import { Tree } from '@react-x11/components/tree';
|
|
474
|
+
|
|
475
|
+
<Tree items={[{ id: 'src', label: 'src', children: [...] }]} />;
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
The default look is plain on purpose — a chevron, no branch lines, just
|
|
479
|
+
indentation — and three things underneath are why the successor is out here
|
|
480
|
+
rather than in core:
|
|
481
|
+
|
|
482
|
+
- **It reads your data where it lies.** `getId` / `getChildren` / `isBranch`
|
|
483
|
+
and friends mean a filesystem listing, an AST or a normalized store is
|
|
484
|
+
rendered without being copied into a shape the component preferred. The
|
|
485
|
+
defaults describe `{ id, label, children }`, so a tree of that shape
|
|
486
|
+
configures nothing.
|
|
487
|
+
- **It virtualizes.** Past a couple of hundred visible rows it builds only
|
|
488
|
+
the slice on screen and stands two spacers in for the rest, so a hundred
|
|
489
|
+
thousand rows cost what forty do.
|
|
490
|
+
- **Every visible part is a seam** — the twisty, the branch edge down the
|
|
491
|
+
indent, the label, the row's contents, and the subtree container in
|
|
492
|
+
`layout="nested"` — each with a style override beside it.
|
|
493
|
+
|
|
494
|
+
`npm run examples:tree` is a file explorer over the real filesystem, lazily
|
|
495
|
+
listed, with folder glyphs and a dotted branch edge through those seams.
|
|
496
|
+
[The reference](docs/components/tree.md) has the rest.
|
|
497
|
+
|
|
498
|
+
## The data table
|
|
499
|
+
|
|
500
|
+
`<Table>` is a **successor to react-x11's own `<Table>`** — the same
|
|
501
|
+
relationship the tree has to core's: nothing here imports it, and the prop
|
|
502
|
+
names core call sites already use mean migrating is changing the import.
|
|
503
|
+
|
|
504
|
+
```jsx
|
|
505
|
+
import { Table } from '@react-x11/components/table';
|
|
506
|
+
|
|
507
|
+
<Table
|
|
508
|
+
rows={files}
|
|
509
|
+
columns={[
|
|
510
|
+
{ id: 'name', label: 'Name', flex: 1 },
|
|
511
|
+
{ id: 'size', label: 'Size', width: 96, align: 'end' },
|
|
512
|
+
]}
|
|
513
|
+
/>;
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
That is the whole basic setup — header, sort on click, selection, resizable
|
|
517
|
+
columns, theme colours — and the design rule above every other one is that
|
|
518
|
+
**ceremony is additive**: sorting, multi-selection, custom cells, and
|
|
519
|
+
virtualization are independent opt-ins on this same element, never a second
|
|
520
|
+
API. Two things underneath are why the successor lives out here:
|
|
521
|
+
|
|
522
|
+
- **Rows may be any height.** Declare `rowHeight` and the visible slice is
|
|
523
|
+
arithmetic, core's model; omit it and drawn rows are measured, the tree's
|
|
524
|
+
model — so a cell that wraps or stacks lines keeps an honest scrollbar,
|
|
525
|
+
at a hundred thousand rows.
|
|
526
|
+
- **Every visible part is a seam** — the cell, the header cell, the row's
|
|
527
|
+
content, the empty state, and a `styles` bag whose row/cell entries
|
|
528
|
+
follow row state.
|
|
529
|
+
|
|
530
|
+
`npm run examples:table` shows the ladder in one window.
|
|
531
|
+
[The reference](docs/components/table.md) has the rest;
|
|
532
|
+
[the PRD](docs/prd-table.md) has the prior-art survey and the reasons.
|
|
533
|
+
|
|
534
|
+
## The code editor
|
|
535
|
+
|
|
536
|
+
A multiline editor for code-shaped input — a SQL box, a shell one-liner, a
|
|
537
|
+
config field, a small IDE pane:
|
|
538
|
+
|
|
539
|
+
```jsx
|
|
540
|
+
import {
|
|
541
|
+
CodeEditor,
|
|
542
|
+
sql,
|
|
543
|
+
sqlCompletionSource,
|
|
544
|
+
keywordCompletionSource,
|
|
545
|
+
} from '@react-x11/components/code-editor';
|
|
546
|
+
|
|
547
|
+
<CodeEditor
|
|
548
|
+
language={sql()}
|
|
549
|
+
value={query}
|
|
550
|
+
onChange={(ev) => setQuery(ev.value)}
|
|
551
|
+
completionSources={[
|
|
552
|
+
sqlCompletionSource({ users: ['id', 'name'] }),
|
|
553
|
+
keywordCompletionSource(),
|
|
554
|
+
]}
|
|
555
|
+
lineNumbers
|
|
556
|
+
style={{ flexGrow: 1 }}
|
|
557
|
+
/>;
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Editing is the full expected set: selection (keyboard and mouse, word and
|
|
561
|
+
line variants), undo/redo with coalescing, X11 clipboard including PRIMARY
|
|
562
|
+
and middle-click paste, auto-indent, Tab/Shift+Tab indentation, Ctrl+/
|
|
563
|
+
comment toggling, bracket matching, and LSP-shaped `diagnostics` squiggles.
|
|
564
|
+
Escape then Tab leaves the field. Ctrl+Space asks for completions.
|
|
565
|
+
|
|
566
|
+
Languages are pluggable, three ways:
|
|
567
|
+
|
|
568
|
+
- **Built-in, zero dependencies**: `sql()`, `shell()`, `glsl()`,
|
|
569
|
+
`javascript()` (`{ typescript: true }` for TS), `json()` — hand-written
|
|
570
|
+
stream tokenizers on a CodeMirror-5-style line-state engine, or write your
|
|
571
|
+
own with `streamLanguage(…)` in ~50 lines.
|
|
572
|
+
- **The CodeMirror grammar world**: `lezerLanguage({ name, parser })` runs
|
|
573
|
+
any `@lezer/<lang>` parser. Install the grammar you want; nothing lezer
|
|
574
|
+
ships with this package.
|
|
575
|
+
- **The VS Code grammar world**: `textMateLanguage({ name, grammar })` runs
|
|
576
|
+
an initialized TextMate grammar (via `vscode-textmate` or shiki's core) —
|
|
577
|
+
their tokenizer is line-state shaped too, so it drops straight in.
|
|
578
|
+
|
|
579
|
+
Completion sources are one async function each, deliberately the shape of an
|
|
580
|
+
LSP `textDocument/completion` call, so a language-server client is "just
|
|
581
|
+
another source". `npm run examples:code-editor` shows the three input-field
|
|
582
|
+
use cases side by side.
|
|
583
|
+
|
|
584
|
+
## The graph editor
|
|
585
|
+
|
|
586
|
+
A directed graph you can edit — a pipeline, a state machine, a dependency
|
|
587
|
+
map, a node-based tool. The surface is [react-flow][rf]'s, so a graph
|
|
588
|
+
described for that is described for this:
|
|
589
|
+
|
|
590
|
+
```jsx
|
|
591
|
+
import {
|
|
592
|
+
Flow,
|
|
593
|
+
useNodesState,
|
|
594
|
+
useEdgesState,
|
|
595
|
+
addEdge,
|
|
596
|
+
} from '@react-x11/components/flow';
|
|
597
|
+
|
|
598
|
+
const [nodes, setNodes, onNodesChange] = useNodesState([
|
|
599
|
+
{ id: 'read', position: { x: 0, y: 0 }, data: { label: 'read' } },
|
|
600
|
+
{ id: 'parse', position: { x: 0, y: 120 }, data: { label: 'parse' } },
|
|
601
|
+
]);
|
|
602
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState([
|
|
603
|
+
{ id: 'r-p', source: 'read', target: 'parse', label: 'bytes' },
|
|
604
|
+
]);
|
|
605
|
+
|
|
606
|
+
<Flow
|
|
607
|
+
nodes={nodes}
|
|
608
|
+
edges={edges}
|
|
609
|
+
onNodesChange={onNodesChange}
|
|
610
|
+
onEdgesChange={onEdgesChange}
|
|
611
|
+
onConnect={(c) => setEdges((es) => addEdge(c, es))}
|
|
612
|
+
fitView
|
|
613
|
+
minimap
|
|
614
|
+
style={{ flexGrow: 1 }}
|
|
615
|
+
/>;
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Nothing mutates the arrays: every gesture arrives as a _change_ the app
|
|
619
|
+
applies (`applyNodeChanges`, `applyEdgeChanges`, `addEdge`), which is what
|
|
620
|
+
makes `nodes`/`edges` an ordinary controlled prop — and undo a matter of not
|
|
621
|
+
applying one. `defaultNodes`/`defaultEdges` give the uncontrolled form.
|
|
622
|
+
|
|
623
|
+
Drag a node to move it, a handle to connect two, the pane to pan, Shift+drag
|
|
624
|
+
to box-select; the wheel zooms, Delete removes the selection (with the edges
|
|
625
|
+
that would dangle), Ctrl+A selects everything, the arrows nudge or pan, `0`
|
|
626
|
+
frames the graph. Edges route as bezier, smoothstep, step or straight, carry
|
|
627
|
+
labels and arrowheads, and animate. `background`, `minimap` and `controls`
|
|
628
|
+
are props rather than child components.
|
|
629
|
+
|
|
630
|
+
**The default node type is a `paint`, not a React component**, and that is
|
|
631
|
+
the one place this is deliberately not react-flow. react-flow gives every
|
|
632
|
+
node a DOM subtree and pans and zooms with a CSS transform, so the browser
|
|
633
|
+
moves ten thousand boxes for free. This renderer has no transform — `style`
|
|
634
|
+
is yoga plus paint — so the same design would re-render and re-lay-out every
|
|
635
|
+
node on every pointer step of a pan. The pane draws the graph instead:
|
|
636
|
+
panning becomes two numbers and one node's repaint, zoom scales text along
|
|
637
|
+
with everything else, and React is not involved at all unless the graph
|
|
638
|
+
itself changed.
|
|
639
|
+
|
|
640
|
+
```jsx
|
|
641
|
+
const nodeTypes = {
|
|
642
|
+
task: {
|
|
643
|
+
size: { width: 150, height: 52 },
|
|
644
|
+
handles: [
|
|
645
|
+
{ type: 'target', position: 'left' },
|
|
646
|
+
{ type: 'source', position: 'right', id: 'ok', label: 'ok' },
|
|
647
|
+
{ type: 'source', position: 'right', id: 'err', offset: 0.8 },
|
|
648
|
+
],
|
|
649
|
+
paint({ rect, zoom, selected, palette, painter, node }) {
|
|
650
|
+
painter.rect(rect.x, rect.y, rect.width, rect.height, 6 * zoom, {
|
|
651
|
+
fill: palette.nodeBackground,
|
|
652
|
+
stroke: selected ? palette.accent : palette.nodeBorder,
|
|
653
|
+
lineWidth: selected ? 2 : 1,
|
|
654
|
+
});
|
|
655
|
+
painter.text(
|
|
656
|
+
node.data.label,
|
|
657
|
+
rect.x + rect.width / 2,
|
|
658
|
+
rect.y + rect.height / 2,
|
|
659
|
+
{
|
|
660
|
+
size: 13 * zoom,
|
|
661
|
+
align: 'center',
|
|
662
|
+
baseline: 'middle',
|
|
663
|
+
color: palette.text,
|
|
664
|
+
},
|
|
665
|
+
);
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
};
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### Nodes that hold real widgets
|
|
672
|
+
|
|
673
|
+
Drawing is right for the nodes there are a lot of. It is not right for a node
|
|
674
|
+
whose body is a form, so a node type may `render` one instead: an ordinary
|
|
675
|
+
react-x11 tree, mounted in a box the pane positions and sizes over the node,
|
|
676
|
+
and laid out by yoga inside it.
|
|
677
|
+
|
|
678
|
+
```jsx
|
|
679
|
+
const nodeTypes = {
|
|
680
|
+
options: {
|
|
681
|
+
size: { width: 268, height: 212 },
|
|
682
|
+
headerHeight: 26, // the strip left for the title, and for dragging
|
|
683
|
+
handles: [{ type: 'source', position: 'right' }],
|
|
684
|
+
render: ({ node }) => (
|
|
685
|
+
<box style={{ flexGrow: 1, padding: 8, gap: 7 }}>
|
|
686
|
+
<text style={{ fontSize: 11, color: '$textMuted' }}>build options</text>
|
|
687
|
+
<Checkbox
|
|
688
|
+
label="strict"
|
|
689
|
+
checked={node.data.strict}
|
|
690
|
+
onChange={(ev) => patch(node.id, { strict: ev.value })}
|
|
691
|
+
/>
|
|
692
|
+
<textarea
|
|
693
|
+
value={node.data.text}
|
|
694
|
+
onChange={(ev) => patch(node.id, { text: ev.value })}
|
|
695
|
+
style={{ flexGrow: 1, flexShrink: 1, minHeight: 0 }}
|
|
696
|
+
/>
|
|
697
|
+
</box>
|
|
698
|
+
),
|
|
699
|
+
},
|
|
700
|
+
};
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
Everything in there behaves the way it does anywhere else: the checkbox takes
|
|
704
|
+
clicks, the textarea takes the keyboard — Delete deletes _text_ while it has
|
|
705
|
+
the focus, not the node — and the buttons draw their own hover and pressed
|
|
706
|
+
states. Three things follow, and all three are the point:
|
|
707
|
+
|
|
708
|
+
- **It re-renders as the viewport moves.** That is the cost the drawn path
|
|
709
|
+
exists to avoid, so it is paid by the nodes that ask for it and no others.
|
|
710
|
+
- **It does not scale with the zoom.** The box does; there is no transform
|
|
711
|
+
here. Content is laid out to the zoomed box at its natural size and
|
|
712
|
+
clipped, and below `zoom` 0.6 it is not mounted at all — the pane draws the
|
|
713
|
+
card instead.
|
|
714
|
+
- **`headerHeight` is what keeps the node draggable.** The body starts below
|
|
715
|
+
it, so there is always somewhere to grab that is not a text field.
|
|
716
|
+
|
|
717
|
+
Add `resizable` to such a node and it grows eight grips on its border while
|
|
718
|
+
it is selected; drag one and the widgets inside reflow with it. The gesture
|
|
719
|
+
arrives as a `dimensions` change (with a `position` one when the grip moved
|
|
720
|
+
the node's origin), applied by the same `applyNodeChanges` as everything
|
|
721
|
+
else. `minWidth`/`minHeight` are the floor.
|
|
722
|
+
|
|
723
|
+
`npm run examples:flow` is a working pipeline editor, and
|
|
724
|
+
`npm run examples:flow-stress` is the measured one: two scene buttons, a pan
|
|
725
|
+
loop, and a live count of X requests and bytes per frame.
|
|
726
|
+
|
|
727
|
+
[rf]: https://reactflow.dev/
|
|
728
|
+
|
|
729
|
+
## The user's real calendar
|
|
730
|
+
|
|
731
|
+
`useDesktopCalendarEvents` reads the calendars the desktop already has —
|
|
732
|
+
Google, Microsoft, CalDAV, local — through Evolution Data Server over D-Bus.
|
|
733
|
+
**Your app never sees a credential and never runs an OAuth flow**, because the
|
|
734
|
+
desktop did that already, in Settings.
|
|
735
|
+
|
|
736
|
+
```jsx
|
|
737
|
+
import { Calendar, useDesktopCalendarEvents } from '@react-x11/components';
|
|
738
|
+
|
|
739
|
+
function Month({ from, to }) {
|
|
740
|
+
const { byDay } = useDesktopCalendarEvents({ from, to, watch: true });
|
|
741
|
+
|
|
742
|
+
return (
|
|
743
|
+
<Calendar
|
|
744
|
+
dayContent={(day, state) =>
|
|
745
|
+
(byDay.get(day) ?? []).slice(0, 3).map((ev, i) => (
|
|
746
|
+
<box
|
|
747
|
+
key={i}
|
|
748
|
+
style={{
|
|
749
|
+
width: 4,
|
|
750
|
+
height: 4,
|
|
751
|
+
borderRadius: 2,
|
|
752
|
+
backgroundColor: state.selected
|
|
753
|
+
? state.color
|
|
754
|
+
: (ev.calendar.color ?? '$accent'),
|
|
755
|
+
}}
|
|
756
|
+
/>
|
|
757
|
+
))
|
|
758
|
+
}
|
|
759
|
+
/>
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
The keys `byDay` uses are exactly the `'YYYY-MM-DD'` days `dayContent` is
|
|
765
|
+
handed, so nothing sits between the two.
|
|
766
|
+
|
|
767
|
+
Expanding recurring events needs [`ical.js`](https://github.com/kewisch/ical.js),
|
|
768
|
+
which is an **optional** dependency — install it if you want events:
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
npm install ical.js
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
Without it, or with no session bus, or on a desktop with no Evolution Data
|
|
775
|
+
Server, `status` is `'unavailable'` and the calendar simply renders without
|
|
776
|
+
dots. None of those is an error; they are ordinary states of a healthy
|
|
777
|
+
machine. `npm run examples:calendar` in this repo is the whole thing working.
|
|
778
|
+
|
|
779
|
+
## Hosting another X client: `<Terminal>` and `<MediaPlayer>`
|
|
780
|
+
|
|
781
|
+
These two are the same component twice, and they are what core's `<foreign>`
|
|
782
|
+
element was added for: a react-x11 app can now **host** another X client
|
|
783
|
+
rather than only drawing its own pixels.
|
|
784
|
+
|
|
785
|
+
```jsx
|
|
786
|
+
import { Terminal } from '@react-x11/components';
|
|
787
|
+
|
|
788
|
+
<Terminal
|
|
789
|
+
command={['bash', '-lc', 'npm test']}
|
|
790
|
+
cwd={projectDir}
|
|
791
|
+
style={{ flexGrow: 1 }}
|
|
792
|
+
onExit={({ code }) => setPassed(code === 0)}
|
|
793
|
+
onTitleChange={setTabLabel}
|
|
794
|
+
fallback={<text>Install xterm to use the console.</text>}
|
|
795
|
+
/>;
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
```jsx
|
|
799
|
+
import { MediaPlayer } from '@react-x11/components';
|
|
800
|
+
|
|
801
|
+
<MediaPlayer
|
|
802
|
+
src={file}
|
|
803
|
+
aspectRatio="16:9"
|
|
804
|
+
volume={0.8}
|
|
805
|
+
style={{ flexGrow: 1 }}
|
|
806
|
+
onProgress={({ position, duration }) => setScrub(position / duration)}
|
|
807
|
+
onEnded={next}
|
|
808
|
+
/>;
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
Mechanically: a `<foreign>` with no `windowId` adopts whatever is put inside
|
|
812
|
+
it, the container's X window id arrives in `onReady`, and the component
|
|
813
|
+
spawns `xterm -into $WID` or `mpv --wid=$WID` into it. Layout, focus, the
|
|
814
|
+
ICCCM configure and handing the client back untouched on unmount are all
|
|
815
|
+
core's.
|
|
816
|
+
|
|
817
|
+
**Nothing is a hard dependency.** No emulator and no player is an ordinary
|
|
818
|
+
state of a healthy machine, so `backend` defaults to `'auto'` and picks the
|
|
819
|
+
first of xterm / rxvt-unicode / alacritty (or mpv / VLC) that is actually
|
|
820
|
+
installed; with none of them, `fallback` renders and `onError` gets a
|
|
821
|
+
`BackendUnavailableError` naming what was looked for.
|
|
822
|
+
|
|
823
|
+
Four things worth knowing before reaching for them:
|
|
824
|
+
|
|
825
|
+
- **The client's window stacks above everything you draw.** Same rule
|
|
826
|
+
`<glarea>` has. A transport bar or a HUD cannot be a `<box>` over the
|
|
827
|
+
surface — put it beside the element, or in a sibling `<popup>`.
|
|
828
|
+
- **The terminal is themed by default.** Background, foreground and cursor
|
|
829
|
+
come from the react-x11 palette, so a pane looks like part of the app.
|
|
830
|
+
`colors` overrides any of it, and `colors={{}}` leaves the emulator on its
|
|
831
|
+
own defaults.
|
|
832
|
+
- **`src`, `volume`, `muted` and `paused` are live commands**, sent over
|
|
833
|
+
mpv's JSON IPC socket — changing them does not respawn the player. Under
|
|
834
|
+
VLC that channel is write-only, so play/pause/seek/volume work and
|
|
835
|
+
`onProgress` never fires; `handle.reportsProgress` says which you have.
|
|
836
|
+
- **`write()` needs the pty to be ours**, so it works on `backend="vt"`
|
|
837
|
+
below and returns `false` on the embedded emulators: the pty there is
|
|
838
|
+
xterm's, and synthetic key events are refused by xterm
|
|
839
|
+
(`allowSendEvents`) and dropped by alacritty. An app can feature-test with
|
|
840
|
+
the call itself.
|
|
841
|
+
|
|
842
|
+
`npm run examples:terminal` and
|
|
843
|
+
`npm run examples:media-player -- <file>` are both working programs.
|
|
844
|
+
|
|
845
|
+
Both take a `processes` prop — the `ProcessHost` seam from
|
|
846
|
+
`@react-x11/components/embed` — so the child can be run somewhere other than
|
|
847
|
+
this machine, and so the test suite can assert what _would_ have been spawned
|
|
848
|
+
without an xterm in CI.
|
|
849
|
+
|
|
850
|
+
### `<Terminal backend="vt">` — the terminal this package draws itself
|
|
851
|
+
|
|
852
|
+
One prop changes the terminal from a hosted X client into a native element: a
|
|
853
|
+
pty (through a pluggable `PtyHost`), [`@xterm/headless`][xterm-headless] as
|
|
854
|
+
the escape-sequence state machine, and a cell-grid renderer that draws with
|
|
855
|
+
XRender glyph runs into a retained offscreen surface, scrolls with a
|
|
856
|
+
server-side copy, and coalesces onto react-x11's vblank-paced frame clock.
|
|
857
|
+
|
|
858
|
+
```jsx
|
|
859
|
+
<Terminal
|
|
860
|
+
backend="vt"
|
|
861
|
+
command={['bash', '-l']}
|
|
862
|
+
cursorStyle="bar"
|
|
863
|
+
bell="visual"
|
|
864
|
+
style={{ flexGrow: 1 }}
|
|
865
|
+
onSelectionChange={setCopied}
|
|
866
|
+
fallback={<text>Install a pty module: npm i node-pty</text>}
|
|
867
|
+
/>
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
What it buys over the embedded emulators:
|
|
871
|
+
|
|
872
|
+
- **It works with nothing installed** — no xterm, no alacritty. That is why
|
|
873
|
+
`backend="auto"` (the default) now ends here instead of at the `fallback`:
|
|
874
|
+
the ladder is xterm → urxvt → alacritty → vt.
|
|
875
|
+
- **`write()` is real**, and with it `cols`/`rows`, `resizeToFit()`,
|
|
876
|
+
`selection()`, `scrollLines()` and `serialize()` on the handle.
|
|
877
|
+
- **It is a native element, not a hole punched in the window.** Theme colours
|
|
878
|
+
apply exactly (`colors.palette` included, which urxvt cannot take at all),
|
|
879
|
+
a `<popup>` composites _above_ it, and focus follows the app's rules.
|
|
880
|
+
- **It is testable without a display.** A fake pty plus the in-process X
|
|
881
|
+
server gives byte-in/pixel-out tests; `test/terminal-vt.test.ts` is one.
|
|
882
|
+
|
|
883
|
+
The dependencies stay optional, and the split is deliberate:
|
|
884
|
+
`@xterm/headless` is an **optionalDependency** (2 MB, installs by default —
|
|
885
|
+
nothing else would bring it), while the pty is an **optional peer**, either
|
|
886
|
+
`node-pty` or `@lydell/node-pty`, probed in that order. node-pty unpacks to
|
|
887
|
+
64 MB and builds a native addon, which is not something a package a calendar
|
|
888
|
+
app installed may drag in. So an app installs the one it wants:
|
|
889
|
+
|
|
890
|
+
```bash
|
|
891
|
+
npm i node-pty # or: npm i @lydell/node-pty
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
With neither present, `status` is `'unavailable'` and `fallback` renders — an
|
|
895
|
+
ordinary state of a healthy machine, never a throw. `onError` says _which_
|
|
896
|
+
half is missing, and separates "nothing installed" from "installed but it
|
|
897
|
+
would not load", because a native module built for another Node ABI looks
|
|
898
|
+
exactly like a missing one from the outside and "install it" is then the
|
|
899
|
+
wrong advice.
|
|
900
|
+
|
|
901
|
+
None of it costs anything to an app that does not use it: the whole vt
|
|
902
|
+
module, `registerElement('vtterm')` included, sits behind a dynamic
|
|
903
|
+
`import()` taken only when the backend is selected, and
|
|
904
|
+
`test/treeshake.test.ts` asserts the terminal's entry chunk does not contain
|
|
905
|
+
it.
|
|
906
|
+
|
|
907
|
+
Keyboard, mouse and selection are what a terminal user expects: xterm-compatible
|
|
908
|
+
key encoding (application cursor/keypad modes, the modifier parameter
|
|
909
|
+
scheme, `Alt` as an ESC prefix), mouse reporting in the tracking mode the
|
|
910
|
+
program asked for (with Shift as the universal "let me select instead"
|
|
911
|
+
override), char/word/line selection that publishes PRIMARY, middle-click
|
|
912
|
+
paste, Ctrl+Shift+C/V, bracketed paste, and OSC 52 clipboard **writes** —
|
|
913
|
+
never reads, which are answered with nothing whatever a program asks for.
|
|
914
|
+
|
|
915
|
+
Escape arms one pass-through Tab, so the terminal is not a keyboard trap;
|
|
916
|
+
Escape still reaches the program, and the arming is off while an alternate-screen
|
|
917
|
+
application (vim, htop) is up, because it owns Esc-then-Tab as real input.
|
|
918
|
+
|
|
919
|
+
#### Bring your own pty
|
|
920
|
+
|
|
921
|
+
`pty` takes a `PtyHost`, and when you pass one **node-pty is never loaded**.
|
|
922
|
+
Anything that carries bytes both ways and can be told a size is a terminal:
|
|
923
|
+
ssh2, a WebSocket, `docker exec`, a serial port, a device over TCP.
|
|
924
|
+
|
|
925
|
+
```ts
|
|
926
|
+
interface PtyHost {
|
|
927
|
+
available(): Promise<boolean>;
|
|
928
|
+
openPty(argv: readonly string[], opts: PtyOptions): Promise<PtySession>;
|
|
929
|
+
environment?(): Record<string, string | undefined>;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
interface PtySession {
|
|
933
|
+
write(data: string): void;
|
|
934
|
+
resize(cols: number, rows: number): void;
|
|
935
|
+
kill(signal?: string): boolean;
|
|
936
|
+
onData(listener: (chunk: string | Uint8Array) => void): void;
|
|
937
|
+
onExit(listener: (info: ExitInfo) => void): void;
|
|
938
|
+
pause?(): void; // flow control, when the transport has it
|
|
939
|
+
resume?(): void;
|
|
940
|
+
readonly pid: number | null; // null is fine — SSH has no pid
|
|
941
|
+
}
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
Three things worth knowing before writing one:
|
|
945
|
+
|
|
946
|
+
- **Hand over bytes when you have bytes.** `onData` accepts a `Uint8Array` (a
|
|
947
|
+
node `Buffer` is one), and passing it through untouched is not an
|
|
948
|
+
optimisation — a `.toString()` on whatever boundary the network chose cuts
|
|
949
|
+
multi-byte UTF-8 in half. The emulator's decoder carries a partial character
|
|
950
|
+
across chunks; a per-chunk decode cannot.
|
|
951
|
+
- **Empty `argv` means "your default shell, wherever you are".** The component
|
|
952
|
+
does not substitute this machine's `$SHELL`, because over ssh that is the
|
|
953
|
+
wrong answer; `nodePtyHost` fills it in locally, and a remote host opens a
|
|
954
|
+
login shell on the far side.
|
|
955
|
+
- **A failed connection is `'exited'`, not `'unavailable'`.** `fallback` is for
|
|
956
|
+
"this machine cannot run a terminal at all"; an ssh host that refused you is
|
|
957
|
+
ordinary bad news, and it arrives through `onError`.
|
|
958
|
+
|
|
959
|
+
[`examples/terminal-ssh.tsx`](examples/terminal-ssh.tsx) is a complete ssh2
|
|
960
|
+
adapter — about eighty lines, with the three gotchas marked — and runs against
|
|
961
|
+
a real host:
|
|
962
|
+
|
|
963
|
+
```bash
|
|
964
|
+
npm i --save-dev ssh2
|
|
965
|
+
SSH_HOST=example.com SSH_USER=me npm run examples:terminal-ssh
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
`npm run examples:terminal-vt` is a working program, and
|
|
969
|
+
[`docs/prd-vt-terminal.md`](docs/prd-vt-terminal.md) is the design document
|
|
970
|
+
behind it.
|
|
971
|
+
|
|
972
|
+
[xterm-headless]: https://www.npmjs.com/package/@xterm/headless
|
|
973
|
+
|
|
974
|
+
## The system tray: `<TrayHost>`
|
|
975
|
+
|
|
976
|
+
The same protocol as the two above, pointed the other way. `<Terminal>` and
|
|
977
|
+
`<MediaPlayer>` spawn a program into a container they own; a tray is handed
|
|
978
|
+
windows by applications that were already running, and the
|
|
979
|
+
[system tray spec](http://specifications.freedesktop.org/systemtray/latest/)
|
|
980
|
+
is XEmbed's biggest surviving consumer.
|
|
981
|
+
|
|
982
|
+
```jsx
|
|
983
|
+
import { TrayHost } from '@react-x11/components';
|
|
984
|
+
|
|
985
|
+
<TrayHost
|
|
986
|
+
orientation="horizontal"
|
|
987
|
+
iconSize={22}
|
|
988
|
+
onDock={(icon) => log(`docked ${icon.id}`)}
|
|
989
|
+
onUndock={(icon) => log(`gone ${icon.id}`)}
|
|
990
|
+
/>;
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
Mounting it takes the `_NET_SYSTEM_TRAY_S<screen>` selection with a real
|
|
994
|
+
server timestamp, publishes `_NET_SYSTEM_TRAY_ORIENTATION`, and broadcasts
|
|
995
|
+
`MANAGER` to the root — which is what makes applications that started before
|
|
996
|
+
the panel go and dock themselves. Each `SYSTEM_TRAY_REQUEST_DOCK` becomes one
|
|
997
|
+
`<foreign>`; unmounting gives the selection back and hands every client to
|
|
998
|
+
the root untouched.
|
|
999
|
+
|
|
1000
|
+
Four things that are decisions rather than gaps:
|
|
1001
|
+
|
|
1002
|
+
- **One tray per display, and a second one says so.** If the selection is
|
|
1003
|
+
already owned, the host reports it through `onConflict`, renders
|
|
1004
|
+
`fallback`, and embeds nothing — a second panel is a configuration mistake,
|
|
1005
|
+
not an exception to throw. Losing the selection later (another tray started)
|
|
1006
|
+
releases every icon, because a panel still drawing icons it no longer holds
|
|
1007
|
+
is the failure users report as "my tray is empty".
|
|
1008
|
+
- **A visual is advertised only when there is one.**
|
|
1009
|
+
`_NET_SYSTEM_TRAY_VISUAL` appears only when the window the icons are
|
|
1010
|
+
embedded into genuinely carries a 32-bit ARGB visual — so put the tray in a
|
|
1011
|
+
`<window transparent>` and icons get real translucency, and anywhere else
|
|
1012
|
+
they fall back to guessing a background rather than drawing black boxes.
|
|
1013
|
+
- **Icons are not tab stops.** Every icon is `focusable={false}`: a tray icon
|
|
1014
|
+
is a click target, and Tab walking through eleven of them (several of which
|
|
1015
|
+
may not have mapped yet) is the worst version of this.
|
|
1016
|
+
- **Reordering moves nodes, it does not re-embed clients.** `sort` is a
|
|
1017
|
+
comparator rather than a list you rebuild, because each `<foreign>` is keyed
|
|
1018
|
+
on the window id and its `windowId` never changes. Unmounting one node and
|
|
1019
|
+
mounting another with the same id parks the client at the root long enough
|
|
1020
|
+
for a window manager to frame it, and the new node then reports
|
|
1021
|
+
`onClientGone` for a live window.
|
|
1022
|
+
|
|
1023
|
+
Balloon messages — `SYSTEM_TRAY_BEGIN_MESSAGE`, the pre-notification-daemon
|
|
1024
|
+
way an icon says something — are reassembled from their 20-byte chunks and
|
|
1025
|
+
forwarded to the desktop's notification service by default. Pass `onMessage`
|
|
1026
|
+
to draw your own bubble instead (which turns the forwarding off), or
|
|
1027
|
+
`notify={false}` to drop them.
|
|
1028
|
+
|
|
1029
|
+
`npm run examples:tray-host` is a one-row panel that is the tray for its
|
|
1030
|
+
display. **StatusNotifierItem is not in this component**: modern applications
|
|
1031
|
+
publish a tray icon over D-Bus, a complete panel supports both, and SNI
|
|
1032
|
+
shares nothing with this except intent — it belongs beside `<TrayHost>`
|
|
1033
|
+
rather than inside it.
|
|
92
1034
|
|
|
93
1035
|
## Roadmap
|
|
94
1036
|
|
|
95
|
-
Candidates to move here
|
|
1037
|
+
Candidates to move here:
|
|
96
1038
|
|
|
97
|
-
- `<markdown>` and `<html>`, currently in react-x11 over ntk's document
|
|
98
|
-
widgets. `<svg>` and `<tex>` stay in ntk. Mermaid was dropped rather than
|
|
99
|
-
extracted — 155 MB of install closure for a grammar.
|
|
100
1039
|
- The 3D scene graph and a Three.js / react-three-fiber-shaped layer, with
|
|
101
1040
|
`<glarea>` itself staying in core.
|
|
102
|
-
- A react-flow-style node/edge graph editor.
|
|
103
1041
|
- `<Tabs>`, undecided — it may well stay in core.
|
|
1042
|
+
- MDX support in `<Markdown>` — see the note in that section.
|
|
1043
|
+
- A StatusNotifierItem host, beside `<TrayHost>` rather than inside it: the
|
|
1044
|
+
D-Bus way modern applications publish a tray icon. It pairs with core's
|
|
1045
|
+
`dbusmenu.js`, and a complete panel wants both.
|
|
1046
|
+
|
|
1047
|
+
`<Table>` above supersedes core's `<Table>` the way `<Tree>` supersedes
|
|
1048
|
+
core's tree; whether core's remainder is stripped down or removed outright
|
|
1049
|
+
is core's decision, still open — `docs/prd-table.md` records the contract.
|
|
1050
|
+
|
|
1051
|
+
`<Markdown>` above **replaces** core's ntk-backed `<markdown>` element, and
|
|
1052
|
+
`<Html>` now replaces `HtmlView` and core's `<html>` (ntk's document widgets
|
|
1053
|
+
are being deprecated). That reverses a decision this README used to record —
|
|
1054
|
+
"no `<html>` successor and no plan for one" — and the reasoning is worth
|
|
1055
|
+
keeping straight: markdown still does **not** render through an HTML pass,
|
|
1056
|
+
because it has an AST of its own and box-and-text composition is better for
|
|
1057
|
+
it. `<Html>` exists because HTML turns up as an _input_ in its own right —
|
|
1058
|
+
mail, release notes, a CMS, an exported report — with no markdown upstream of
|
|
1059
|
+
it to render instead. See [docs/prd-html.md](docs/prd-html.md). `<svg>` and
|
|
1060
|
+
`<tex>` stay in ntk; mermaid was dropped rather than extracted — 155 MB of
|
|
1061
|
+
install closure for a grammar.
|
|
104
1062
|
|
|
105
1063
|
## Contributing
|
|
106
1064
|
|